Створення динамічного поля вибору


136

У мене виникають проблеми, намагаючись зрозуміти, як створити динамічне поле вибору в джанго. У мене створена модель на кшталт:

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()])

Але все, що потрібно зробити, це перерахувати всі шляхові точки, вони не асоціюються з яким-небудь конкретним вершником. Будь-які ідеї? Дякую.

Відповіді:


191

Ви можете відфільтрувати точкові точки, перенісши користувача до форми 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

20
Використовуйте ModelChoiceField, будь то ModelForm чи ні - він працює і в звичайних формах.
Даніель Роузман

9
Що ви робите, коли хочете отримати дані запиту? waypointForm (request.POST) не буде перевірений у першому, тому що даних для перевірки вже немає.
Breedly

1
@Ashok Як можна використовувати віджет CheckboxSelectMultiple в цьому випадку? Особливо для модельної форми.
wasabigeek

2
Якщо ви хочете використовувати CheckboxSelectMultipleвіджет з цим, ви хочете використовувати MultipleChoiceFieldабо ModelMultipleChoiceField. Спочатку, здається, працює ChoiceField, але внутрішня система порушиться, коли ви спробуєте зберегти форму.
coredumperror

1
Дякую @CoreDumpError - я просто боровся з цим протягом майже 2 годин, перш ніж прочитати ваш коментар (так!), І це нарешті змусило все працювати. Інші, будьте обережні, щоб порушити подання форми (питання Unicode), якщо ви плануєте використовувати CheckboxSelectMultipleвіджет із цим кодом. Обов’язково перейдіть ChoiceFormнаMultipleChoiceForm
тихо

11

Існує вбудоване рішення для вашої проблеми: ModelChoiceField .

Як правило, завжди варто намагатися використовувати, ModelFormколи вам потрібно створити / змінити об'єкти бази даних. Працює в 95% випадків, і це набагато чіткіше, ніж створення власної реалізації.


8

проблема в тому, коли ти робиш

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)])

у запиті на оновлення попереднє значення втрачається!


3

Як щодо передачі екземпляра вершника до форми при ініціалізації її?

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) 

2

Під робочим розчином із звичайним полем вибору. моя проблема полягала в тому, що кожен користувач має свої власні варіанти вибору CUSTOM на основі кількох умов.

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

Саме те, що я шукав! Дякую!
Раптор

це полегшило моє життя .. Дякую багато .. :)
Aravind R Pillai

1

Як вказували Брідлі та Лян, рішення Ашока не дозволить вам отримати значення вибору при розміщенні форми.

Один дещо інший, але все ще недосконалий спосіб вирішити це:

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)

Однак це може спричинити деякі проблеми узгодження.


1

Ви можете оголосити поле як першокласний атрибут форми та просто динамічно встановити вибір:

class WaypointForm(forms.Form):
    waypoints = forms.ChoiceField(choices=[])

    def __init__(self, user, *args, **kwargs):
        super().__init__(*args, **kwargs)
        waypoint_choices = [(o.id, str(o)) for o in Waypoint.objects.filter(user=user)]
        self.fields['waypoints'].choices = waypoint_choices

Ви також можете використовувати ModelChoiceField і встановити набір запитів на init аналогічним чином.


0

Якщо вам потрібне поле динамічного вибору в адміністраторі django; Це працює для django> = 2.1.

class CarAdminForm(forms.ModelForm):
    class Meta:
        model = Car

    def __init__(self, *args, **kwargs):
        super(CarForm, self).__init__(*args, **kwargs)

        # Now you can make it dynamic.
        choices = (
            ('audi', 'Audi'),
            ('tesla', 'Tesla')
        )

        self.fields.get('car_field').choices = choices

    car_field = forms.ChoiceField(choices=[])

@admin.register(Car)
class CarAdmin(admin.ModelAdmin):
    form = CarAdminForm

Сподіваюся, це допомагає.

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.