Dinamik bir seçim alanı oluşturma


136

Django'da dinamik bir seçim alanı oluşturmayı anlamaya çalışırken biraz sorun yaşıyorum. Ben bir şey gibi bir model kurmak var:

class rider(models.Model):
     user = models.ForeignKey(User)
     waypoint = models.ManyToManyField(Waypoint)

class Waypoint(models.Model):
     lat = models.FloatField()
     lng = models.FloatField()

Ne yapmaya çalışıyorum bir seçim alanı kim değerlerini o binici (ki oturum açmış kişi olurdu) ile ilişkili yol noktaları vardır.

Şu anda benim formlarda init geçersiz kılınıyorum:

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

Ancak tüm yapmanız gereken tüm yol noktalarını listelemek, herhangi bir binici ile ilişkili değil. Herhangi bir fikir? Teşekkürler.

Yanıtlar:


191

kullanıcıyı form init'e geçirerek ara noktalara filtre uygulayabilirsiniz

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

formu başlatırken sizden kullanıcıyı geçirin

form = waypointForm(user)

model halinde

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
ModelCorm olsun ya da olmasın ModelChoiceField kullanın - normal formlarda da çalışır.
Daniel Roseman

9
İstek verilerini almak istediğinizde ne yaparsınız? waypointForm (request.POST) ilkinde doğrulama yapmaz, çünkü doğrulanacak veriler artık mevcut değildir.
Aralık'ta Breedly

1
@Ashok CheckboxSelectMultiple widget'ı bu örnekte nasıl kullanılabilir? Özellikle model formu için.
wasabigeek

2
Kullanmak isterseniz CheckboxSelectMultiplebununla widget'ı, kullanmak isteyeceksiniz MultipleChoiceFieldya ModelMultipleChoiceField. İlk başta, işe yarıyor gibi görünüyor ChoiceField, ancak formu kaydetmeye çalıştığınızda iç kısım kırılacak.
coredumperror

1
Teşekkür ederim @CoreDumpError - sadece yorumunuzu (doh!) Okumadan önce yaklaşık 2 saat boyunca savaştı ve bu sonunda her şeyi işe yaradı. Diğerleri, CheckboxSelectMultiplebu kodla widget'ı kullanmayı planlıyorsanız form gönderiminizi (unicode sorunları) kırmayı unutmayın . Değişime mutlaka ChoiceFormiçinMultipleChoiceForm
sofly

11

Sorununuz için yerleşik bir çözüm var: ModelChoiceField .

Genellikle, ModelFormveritabanı nesneleri oluşturmanız / değiştirmeniz gerektiğinde her zaman kullanmaya değer . Vakaların% 95'inde çalışır ve kendi uygulamanızı oluşturmaktan çok daha temizdir.


8

sorun şu ki

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

bir güncelleme talebinde, önceki değer kaybolur!


3

Sürücü örneğini başlatırken forma geçirmeye ne dersiniz?

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

Normal seçim alanı ile çalışma çözümü altında. Benim sorunum, her kullanıcının birkaç koşula dayalı kendi ÖZEL seçim alanı seçenekleri olmasıydı.

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

Tam aradığım şey! Teşekkürler!
Raptor

Bu hayatımı kolaylaştırdı .. Çok teşekkürler .. :)
Aravind R Pillai

1

Breedly ve Liang'ın işaret ettiği gibi, Ashok'un çözümü formu gönderirken seçilen değeri almanızı engelleyecektir.

Bunu çözmek için biraz farklı, ama yine de kusurlu bir yol:

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)

Bu yine de bazı uyum sorunlarına neden olabilir.


1

Alanı formunuzun birinci sınıf niteliği olarak bildirebilir ve yalnızca seçimleri dinamik olarak ayarlayabilirsiniz:

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

Ayrıca bir ModelChoiceField kullanabilirsiniz ve init üzerinde queryset benzer şekilde ayarlayabilirsiniz.


0

Django admin'de dinamik bir seçim alanına ihtiyacınız varsa; Bu django> = 2.1 için çalışır.

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

Bu yardımcı olur umarım.

Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.