У меня возникли проблемы с попыткой понять, как создать динамическое поле выбора в django. У меня есть модель, создающая что-то вроде:
class rider(models.Model):
user = models.ForeignKey(User)
waypoint = models.ManyToManyField(Waypoint)
class Waypoint(models.Model):
lat = models.FloatField()
lng = models.FloatField()
То, что я пытаюсь сделать, это создать выбор. Значение поля - это путевые точки, связанные с этим всадником (который был бы зарегистрированным человеком).
В настоящее время я переопределяю init в своих формах:
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()])
Но все, что делает, это список всех путевых точек, они не связаны с каким-либо конкретным всадником. Есть идеи? Спасибо.
вы можете отфильтровать путевые точки, передав пользователю форму 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)]
)
из вашего представления при запуске формы передайте пользователю
form = waypointForm(user)
в случае модельной формы
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
Есть встроенное решение для вашей проблемы: ModelChoiceField.
Как правило, всегда стоит использовать ModelForm
, когда вам нужно создавать/изменять объекты базы данных. Работает в 95% случаев и намного чище, чем создание собственной реализации.
проблема в том, что вы делаете
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)])
в запросе на обновление, предыдущее значение будет потеряно!
Как передать экземпляр rider в форму при его инициализации?
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)
Под рабочим решением с нормальным полем выбора. моя проблема заключалась в том, что каждый пользователь имеет свои собственные параметры выбора ПОЛЬЗОВАТЕЛЯ, основанные на нескольких условиях.
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
Как указано Breedly и Liang, решение Ashok не позволит вам получить значение выбора при отправке формы.
Один немного другой, но еще несовершенный способ решить это:
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)
Это может вызвать некоторые проблемы совпадения.