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

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

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