python - update - Creando un campo de elección dinámico
formularios avanzados django (6)
Tengo problemas para tratar de comprender cómo crear un campo de elección dinámica en django. Tengo un modelo configurado algo así como:
class rider(models.Model):
user = models.ForeignKey(User)
waypoint = models.ManyToManyField(Waypoint)
class Waypoint(models.Model):
lat = models.FloatField()
lng = models.FloatField()
Lo que intento hacer es crear una opción Campo cuyos valores son los puntos de ruta asociados con ese usuario (que sería la persona que inició sesión).
Actualmente estoy anulando init en mis formularios de esta manera:
class waypointForm(forms.Form):
def __init__(self, *args, **kwargs):
super(joinTripForm, self).__init__(*args, **kwargs)
self.fields[''waypoints''] = forms.ChoiceField(choices=[ (o.id, str(o)) for o in Waypoint.objects.all()])
Pero todo lo que hace es enumerar todos los waypoints, no están asociados con ningún corredor en particular. ¿Algunas ideas? Gracias.
¿Qué tal pasar la instancia del piloto al formulario al inicializarlo?
class WaypointForm(forms.Form):
def __init__(self, rider, *args, **kwargs):
super(joinTripForm, self).__init__(*args, **kwargs)
qs = rider.Waypoint_set.all()
self.fields[''waypoints''] = forms.ChoiceField(choices=[(o.id, str(o)) for o in qs])
# In view:
rider = request.user
form = WaypointForm(rider)
Como señalan Breedly y Liang, la solución de Ashok le impedirá obtener el valor seleccionado al publicar el formulario.
Una manera ligeramente diferente, pero aún imperfecta, de resolver eso sería:
class waypointForm(forms.Form):
def __init__(self, user, *args, **kwargs):
self.base_fields[''waypoints''].choices = self._do_the_choicy_thing()
super(waypointForm, self).__init__(*args, **kwargs)
Sin embargo, esto podría causar algunos problemas de concurrencia.
Debajo de la solución de trabajo con el campo de elección normal. Mi problema es que cada usuario tiene sus propias opciones de campo de elección CUSTOM basadas en algunas condiciones.
class SupportForm(BaseForm):
affiliated = ChoiceField(required=False, label=''Fieldname'', choices=[], widget=Select(attrs={''onchange'': ''sysAdminCheck();''}))
def __init__(self, *args, **kwargs):
self.request = kwargs.pop(''request'', None)
grid_id = get_user_from_request(self.request)
for l in get_all_choices().filter(user=user_id):
admin = ''y'' if l in self.core else ''n''
choice = ((''%s_%s'' % (l.name, admin)), (''%s'' % l.name))
self.affiliated_choices.append(choice)
super(SupportForm, self).__init__(*args, **kwargs)
self.fields[''affiliated''].choices = self.affiliated_choice
Hay una solución integrada para su problema: ModelChoiceField .
En general, siempre vale la pena tratar de usar ModelForm
cuando necesite crear / cambiar objetos de base de datos. Funciona en el 95% de los casos y es mucho más limpio que crear su propia implementación.
el problema es cuando lo haces
def __init__(self, user, *args, **kwargs):
super(waypointForm, self).__init__(*args, **kwargs)
self.fields[''waypoints''] = forms.ChoiceField(choices=[ (o.id, str(o)) for o in Waypoint.objects.filter(user=user)])
en una solicitud de actualización, ¡el valor anterior se perderá!
puede filtrar los puntos de referencia pasando al usuario al formulario init
class waypointForm(forms.Form):
def __init__(self, user, *args, **kwargs):
super(waypointForm, self).__init__(*args, **kwargs)
self.fields[''waypoints''] = forms.ChoiceField(
choices=[(o.id, str(o)) for o in Waypoint.objects.filter(user=user)]
)
desde su vista al iniciar el formulario, pase al usuario
form = waypointForm(user)
en caso de forma de modelo
class waypointForm(forms.ModelForm):
def __init__(self, user, *args, **kwargs):
super(waypointForm, self).__init__(*args, **kwargs)
self.fields[''waypoints''] = forms.ModelChoiceField(
queryset=Waypoint.objects.filter(user=user)
)
class Meta:
model = Waypoint