Невозможно обработать входные данные из 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.

Вернуться на верх