Я понимаю, что можно переопределить набор запросов по умолчанию, «используемый» набором моделей . Это просто ограничивает объекты, для которых создается форма.
Я также нашел вопрос о переполнении стека о фильтрации вариантов ForeignKey в Django ModelForm , но не ModelForm Set и о ограничении доступных вариантов в наборе форм Django , но не Model FormSet. Я включил свою версию этого кода ниже.
Я хочу отрендерить ModelFormSet для школьного класса ('обучающая группа' или 'theclass', чтобы избежать конфликта с ключевым словом 'class') с одним полем, ограниченным набором запросов. Это необходимо для формы редактирования класса учителем, чтобы иметь возможность переназначить учеников в другой класс, но ограничено классами в той же когорте.
My 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']
My 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 %}
{% for field in form.visible_fields %}
{# Include the hidden fields in the form #}
{% if forloop.first %}
{% for hidden in form.hidden_fields %}
{{ hidden }}
{% endfor %}
{% endif %}
{{ field }}
{% if field.errors %}
{% endif %}
{% endfor %}
{% endfor %}
{{ choices }}
Страница отображается со всеми обучающими группами (классами), видимыми в виджете выбора, но тег внизу страницы отображается как: [
, точно показывающий только два класса в 8 классе.
Обратите внимание, что я также прочитал сообщение Джеймса Беннета Итак, вам нужна динамическая форма , как рекомендовано Как я могу ограничить доступные варианты для поля внешнего ключа в django modelformset? , но это требует изменения метода __ init __
в формах.py, и все же единственный способ, которым я знаю, как создать ModelFormSet, - это modelformset_factory, который не включает определение каких-либо классов в forms.py.
В дополнение к помощи Люка Снирингера , вот моя новая запись forms.py. После прочтения Почему я получаю ошибку «Не повторяется объект»? Я понял, что некоторые из моих проблем возникли из-за передачи кортежа методу 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