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= Skil开发者_如何学GolsReference.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.
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
Your code looks almost ok. Try this SkillForm:
class SkillForm(ModelForm):
skill = forms.ModelChoiceField(queryset= SkillsReference.objects.filter(person = self.person)
class Meta:
model = Skills
fields = ( 'person', 'skill')
The difference is that skill is a form's field, should not be in Meta class
EDITED
The above solution is incorrect, but this link describes how to achieve what you want: http://www.zoia.org/blog/2007/04/23/using-dynamic-choices-with-django-newforms-and-custom-widgets/
精彩评论