specified has formularios form fields example django django-models django-forms

has - Listado de valores utilizables solo en OneToOneField Django



post django (2)

Necesitas algo como esto en el método init () de tu formulario.

def __init__(self, *args, **kwargs): super(BarForm, self).__init__(*args, **kwargs) # returns Bar(s) who are not in Foo(s). self.fields[''foo''].queryset = Bar.objects.exclude(id__in=Foo.objects.all().values_list( ''bar_id'', flat=True))

PD: Código no probado.

Quiero enumerar solo los elementos utilizables en OneToOneField no todos los elementos, no es como filtrar los valores en ChoiceField porque tenemos que encontrar solo valores que se puedan usar, que se basa en el principio de si ya se utilizó o no.

Estoy teniendo una definición de modelo de la siguiente manera:

class Foo(models.Model): somefield = models.CharField(max_length=12) class Bar(models.Model): somefield = models.CharField(max_length=12) foo = models.OneToOneField(Foo)

Ahora estoy usando un ModelForm para crear formularios basados ​​en el modelo de Bar como:

class BarForm(ModelForm): class Meta: model = Bar

Ahora el problema está en la forma en que muestra una lista de todos los objetos Foo disponibles en la base de datos en el campo ChoiceField usando el widget de selección de HTML, dado que el campo es OneToOneField django forzará a la asociación única del objeto Bar al objeto Foo, pero dado que muestra todos los elementos utilizables e inutilizables en la lista se vuelve difícil averiguar qué valores serán aceptables en el formulario y los usuarios se ven obligados a utilizar el método hit / trial para encontrar la opción correcta.

¿Cómo puedo cambiar este comportamiento y enumerar solo aquellos elementos en el campo que pueden usarse?


Aunque este es un tema antiguo, lo encontré buscando la misma respuesta.

Específicamente para el OP:

Ajusta tu BarForm para que se vea así:

class BarForm(ModelForm): class Meta: model = Bar def __init__(self, *args, **kwargs): super(BarForm, self).__init__(*args, **kwargs) #only provide Foos that are not already linked to a Bar, plus the Foo that was already chosen for this Bar self.fields[''foo''].queryset = Foo.objects.filter(Q(bar__isnull=True)|Q(bar=self.instance))

Eso debería hacer el truco. Sobrescribe la función init para que pueda editar el campo foo en el formulario, proporcionándole un conjunto de consulta más específico de los Foo disponibles Y (bastante importante) el Foo que ya fue seleccionado.

Para mi propio caso

Mi pregunta original fue: ¿cómo mostrar solo los usuarios disponibles en una relación OneToOne?

El modelo Actor en mi models.py ve así:

class Actor(models.Model): user = models.OneToOneField(User, on_delete=models.CASCADE, related_name = ''peactor'') # lots of other fields and some methods here

En mi admin.py tengo la siguiente clase:

class ActorAdmin(admin.ModelAdmin): # some defines for list_display, actions etc here form = ActorForm

No estaba usando un formulario especial antes (solo confiando en el ModelForm básico que Django suministra por defecto para un ModelAdmin) pero lo necesitaba para la siguiente solución al problema. Entonces, finalmente, en my forms.py tengo:

class ActorForm(forms.ModelForm): def __init__(self, *args, **kwargs): super(ActorForm, self).__init__(*args, **kwargs) #only provide users that are not already linked to an actor, plus the user that was already chosen for this Actor self.fields[''user''].queryset = User.objects.filter(Q(peactor__isnull=True)|Q(peactor=self.instance))

Así que aquí hago un ActorForm y sobrescribo el método __init__ .

self.fields[''user''].queryset =

Establece el conjunto de consulta que utilizará el campo de formulario del usuario. Este formfield es un ModelChoiceField por defecto para OneToOneField (o ForeignKey) en un modelo.

Q(peactor__isnull=True)|Q(peactor=self.instance)

La Q es para objetos Q que ayudan con consultas "complejas" como una instrucción or .

Entonces esta consulta dice: donde peactor no está establecido O donde peactor es el mismo que ya fue seleccionado para este actor

peactor es el related_name para el Actor. De esta forma, solo obtendrá los usuarios que están disponibles, pero también el que no está disponible porque ya está vinculado al objeto que está editando actualmente .

Espero que esto ayude a alguien con la misma pregunta. :-)