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


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.