Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to pass a queryset to a ModelChoiceField using a self.field_value in Django ModelForms

I could explain the whole thing to you but I guess a code speaks clearer than words so:

  class Skills(models.Model):
        skill = models.ForeignKey(ReferenceSkills)
        person = models.ForeignKey(User)

class SkillForm(ModelForm):
    class Meta:
        model = Skills
        fields = ( 'person', 'skill')
    (???)skill = forms.ModelChoiceField(queryset= SkillsReference.objects.filter(person = self.person)

I'm just guessing at how I can do it. But I hope you guys understand what I'm trying to do.

like image 974
Sussagittikasusa Avatar asked May 27 '11 11:05

Sussagittikasusa


2 Answers

Assuming you are using class-based views, you can pass the queryset in your form kwargs and then replace it on form init method:

# views.py
class SkillUpdateView(UpdateView):
    def get_form_kwargs(self, **kwargs):
        kwargs.update({
            'skill_qs': Skills.objects.filter(skill='medium')
        })

        return super(self, SkillUpdateView).get_form_kwargs(**kwargs)


# forms.py
class SkillForm(forms.ModelForm):
    def __init__(self, *args, **kwargs):
        qs = kwargs.pop('skill_ks')
        super(self, SkillForm).__init__(*args, **kwargs)

        self.fields['skill'].queryset = qs

But, personally I prefer this second approach. I get the form instance on the View and than replace the field queryset before django wrap it on the context:

# views.py
class SkillsUpdateView(UpdateView):
    form_class = SkillForm

    def get_form(self, form_class=None):
        form = super().get_form(form_class=self.form_class)
        form.fields['skill'].queryset = Skills.objects.filter(skill='medium')

        return form
like image 156
Victor Guimarães Nunes Avatar answered Oct 06 '22 06:10

Victor Guimarães Nunes


You can ovverride a form structure before you create an instance of the form like:

class SkillForm(ModelForm):
    class Meta:
        model = Skills
        fields = ( 'person', 'skill')

In your view:

SkillForm.base_fields['skill'] = forms.ModelChoiceField(queryset= ...)
form = SkillForm()

You can override it anytime you want in your view, impottant part is, you must do it before creating your form instance with

form = SkillForm()
like image 15
FallenAngel Avatar answered Oct 06 '22 08:10

FallenAngel