Невозможно обработать входные данные из ModelMultipleChoiceField в Django
Я пытаюсь обработать данные, полученные из простой формы Django Model Form, и по какой-то причине не могу получить доступ к группе элементов, выбранных в ModelMultipleChoiceField. Я могу получить доступ только к одному элементу из выбранных элементов в форме.
Модель:
class Student(models.Model):
name = models.CharField(max_length=80)
subjects = models.ManyToManyField(Subject)
house = models.ForeignKey(House, on_delete=models.CASCADE, related_name="students_of_house")
Форма модели:
class AddStudentForm(forms.Form):
name = forms.CharField(label="Full Name")
house = ModelChoiceField(queryset=House.objects.all())
subjects = ModelMultipleChoiceField(queryset=Subject.objects.all())
Функция представления для обработки POST и создания объекта Student.:
def add_student(request):
if request.method == "POST":
name = request.POST["name"]
house = House.objects.get(id=int(request.POST["house"]))
subject_ids = request.POST["subjects"]
new_student = Student(name=name, house=house)
new_student.save()
for sub_id in subject_ids:
new_student.subjects.add(Subject.objects.get(id=int(sub_id))
new_student.save()
return HttpResponseRedirect(reverse("administration:students"))
context = {
"add_student_form": AddStudentForm(),
}
return render(request, "administration/add_student.html", context)
Позже я попробовал использовать маршрут form = AddStudentForm(request.POST)
и if form.is_valid():
, что позволило ему успешно работать. Но мне трудно понять, почему вышеуказанный метод не работает.
Код, который сработал:
def add_student(request):
if request.method == "POST":
form = AddStudentForm(request.POST)
if form.is_valid():
name = form.cleaned_data["name"]
house = form.cleaned_data["house"]
subject_ids = form.cleaned_data["subjects"]
new_student = Student(name=name, house=house)
new_student.save()
for sub_id in subject_ids:
new_student.subjects.add(Subject.objects.get(id=sub_id.id))
new_student.save()
return HttpResponseRedirect(reverse("administration:students"))
context = {
"add_student_form": AddStudentForm(),
}
return render(request, "administration/add_student.html", context)
Почему это работает, а предыдущий вид - нет? Любая помощь будет очень признательна.
Также попробуйте напрямую добавить предметы вместо использования objects.get(), что также не сработало.
В объекте HttpRequest
атрибуты GET
и POST
являются экземплярами QueryDict
[django-docs], который представляет собой класс, похожий на словарь, настроенный на работу с несколькими значениями для одного и того же ключа. Это необходимо, потому что некоторые элементы HTML form
, в частности <select multiple>
, передают несколько значений для одного и того же ключа, подобно тому, с чем вы сейчас столкнулись.
Django Form
обрабатывает получение всех значений за вас, предоставляя вам Iterable
, содержащий все значения в этом поле. Но если вы хотите получить его самостоятельно, вам нужно сделать следующее:
subject_ids = request.POST.getlist("subjects", default=[]) #[1]
[1] You are guaranteed to get a list
unless the default
value provided isn’t a list
.