गतिशील विकल्प क्षेत्र बनाना


136

मुझे यह समझने में थोड़ी परेशानी हो रही है कि django में डायनामिक च्वाइस फील्ड कैसे बनाएं। मेरे पास एक मॉडल सेट है जैसे कि:

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

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

मैं जो करने की कोशिश कर रहा हूं वह एक विकल्प बना है फ़ील्ड व्होस मान वे हैं जो उस राइडर (जो लॉग इन किया गया व्यक्ति होगा) से जुड़े हैं।

वर्तमान में मैं अपने रूपों में इनर को ओवरराइड कर रहा हूं जैसे:

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

आप उपयोगकर्ता को प्रपत्र इनिट में पास करके वेपॉइंट को फ़िल्टर कर सकते हैं

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) पहले एक में मान्य नहीं होगा, क्योंकि डेटा के खिलाफ मान्य करने के लिए अब और नहीं है।
बत्तीसी

1
@Ashok इस उदाहरण में CheckboxSelectMultiple विजेट का उपयोग कैसे किया जा सकता है? खासतौर पर मॉडलफॉर्म के लिए।
wasabigeek

2
यदि आप इसके CheckboxSelectMultipleसाथ विजेट का उपयोग करना चाहते हैं, तो आप उपयोग करना चाहेंगे MultipleChoiceFieldया ModelMultipleChoiceField। सबसे पहले, यह साथ काम करने लगता है ChoiceField, लेकिन जब आप फॉर्म को बचाने की कोशिश करेंगे तो इंटर्ल्स टूट जाएंगे।
coredumperror

1
धन्यवाद @CoreDumpError - अपनी टिप्पणी (doh!) पढ़ने से पहले लगभग 2 घंटे तक यह लड़ाई लड़ी और अंत में इसने सब कुछ काम कर दिया। यदि आप CheckboxSelectMultipleइस कोड के साथ विजेट का उपयोग करने की योजना बनाते हैं, तो अपने फॉर्म सबमिशन (यूनिकोड मुद्दों) को तोड़ने से सावधान रहें । बदलने के ChoiceFormलिए सुनिश्चित करेंMultipleChoiceForm
sofly

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

सामान्य विकल्प क्षेत्र के साथ काम कर रहे समाधान के नीचे। मेरी समस्या यह थी कि प्रत्येक उपयोगकर्ता के पास कुछ शर्तों के आधार पर अपने स्वयं के कस्टमाइज़ विकल्प क्षेत्र होते हैं।

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

ठीक वही जो मेरे द्वारा खोजा जा रहा था! धन्यवाद!
रैप्टर

इसने मेरे जीवन को आसान बना दिया .. बहुत बहुत धन्यवाद .. :)
अरविंद आर पिल्लई

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 Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.