據我所知,有可能override the default queryset 'used' by the modelformset。這只是限制了創建表單的對象。Django過濾器ModelFormSet字段選擇...不同於限制Formset的查詢集
我還發現了一個堆棧溢出問題有關filtering ForeignKey choices in a Django ModelForm,但不是的ModelForm 集約limiting available choices in a Django formset,但不是模式表單集中。我已經在下面包含了我的這個代碼版本。
我想要做的是爲一個學校類('teachinggroup'或'theclass'避免與'class'關鍵字衝突)渲染一個ModelFormSet,其中一個字段受queryset限制。這是爲了教師的班級編輯形式,能夠將學生重新分配給不同的班級,但僅限於同一隊列中的班級。
我的models.py
class YearGroup(models.Model):
intake_year = models.IntegerField(unique=True)
year_group = models.IntegerField(unique=True, default=7)
def __unicode__(self):
return u'%s (%s intake)' % (self.year_group, self.intake_year)
class Meta:
ordering = ['year_group']
class TeachingGroup(models.Model):
year = models.ForeignKey(YearGroup)
teachers = models.ManyToManyField(Teacher)
name = models.CharField(max_length=10)
targetlevel = models.IntegerField()
def __unicode__(self):
return u'Y%s %s' % (self.year.year_group, self.name)
class Meta:
ordering = ['year', 'name']
我views.py
def edit_pupils(request, teachinggroup):
theclass = TeachingGroup.objects.get(name__iexact = teachinggroup)
pupils = theclass.pupil_set.all()
PupilModelFormSet = modelformset_factory(Pupil)
classes_by_year = theclass.year.teachinggroup_set.all()
choices = [t for t in classes_by_year]
# choices = [t.name for t in classes_by_year] #### I also tried this
if request.method == 'POST':
formset = PupilModelFormSet(request.POST,queryset=pupils)
if formset.is_valid():
formset.save()
return redirect(display_class_list, teachinggroup = teachinggroup)
else:
formset = PupilModelFormSet(queryset=pupils)
for form in formset:
for field in form:
if 'Teaching group' == field.label:
field.choices = choices
return render_to_response('reassign_pupils.html', locals())
正如你所看到的,我限制了選擇的查詢集classes_by_year,這是唯一屬於同一類年組。這個查詢集正確顯示,正如你可以在下面呈現的頁面中看到的那樣,但它根本不影響表單字段。
我的模板中選擇小部件
{% for form in formset %}
<tr>
{% for field in form.visible_fields %}
<td> {# Include the hidden fields in the form #}
{% if forloop.first %}
{% for hidden in form.hidden_fields %}
{{ hidden }}
{% endfor %}
{% endif %}
<p><span class="bigtable">{{ field }}</span>
{% if field.errors %}
<p><div class="alert-message error">
{{field.errors|striptags}}</p>
</div>
{% endif %}
</td>
{% endfor %}
</tr>
{% endfor %}
</table>
<input type="submit" value="Submit changes"></p>
</form>
{{ choices }} <!-- included for debugging -->
頁面呈現的所有教學組(類)可見,但在頁面底部的標籤呈現爲:[<TeachingGroup: Y8 82Ma2>, <TeachingGroup: Y8 82Ma3>]
,準確地顯示只有兩個班8年
請注意,我還通過詹姆斯·貝內特後So you want a dynamic form閱讀所推薦的How can I limit the available choices for a foreign key field in a django modelformset?,但涉及到修改__init__
方法forms.py,然而唯一的辦法我知道如何創建一個ModelFormSet是modelformset_factory,它沒有不涉及在forms.py中定義任何類。
繼續從Luke Sneeringer獲得幫助,這裏是我的新forms.py條目。在閱讀Why do I get an object is not iterable error?之後,我意識到我的一些問題來自於將元組賦予field.choices方法,當它期待字典時。我用.queryset的做法相反,它工作正常:
class PupilForm(forms.ModelForm):
def __init__(self, *args, **kwargs):
super(PupilForm, self).__init__(*args, **kwargs)
thepupil = self.instance
classes_by_year = thepupil.teaching_group.year.teachinggroup_set.all()
self.fields['teaching_group'].queryset = classes_by_year
class Meta:
model = Pupil
感謝您的詳細首發,但我承認失敗解釋它。如果我用'__init __(self)'和'__init __()'逐字逐句嘗試,我得到'TypeError:__init __()有一個意外的關鍵字參數'auto_id',它由formset工廠生成。如果我嘗試使用'(self,* args,** kwargs)'和'__init __(* args,** kwargs)'(我只是在黑暗中刺穿),我得到DoesNotExist,並且表單似乎不受約束。如果我嘗試使用'super(PupilForm,self.instance,self)'我得到'AttributeError:'PupilForm'對象沒有屬性'instance'。 – nimasmi
哦,我沒有意識到有爭論。你的第二個猜測是對的。我會更詳細地看看它,並通過編輯回覆您。 –
關於論據的主題,從[上述文章](http://www.b-list.org/weblog/2008/nov/09/dynamic-forms/)繼續我也試過: 'def __init __(自我,學生,* args,** kwargs):' 但得到'__init __()至少需要2個非關鍵字參數(給出1)' – nimasmi