Есть ли способ обойти проблему "Field 'id' expected a number" при работе с набором запросов?

Я работаю над платформой для обучения. Я хочу иметь возможность отслеживать прогресс пользователя по пройденным главам. Я создал новую модель и вставил ее в html с помощью формы. Однако при отправке я получаю ошибку типа TypeError со спецификой: "Поле 'id' ожидало число, но получило <QueryDict: {'csrfmiddlewaretoken': ['YMvOO6ZYGWVVfxfgoFLVEanZ9zK70CrqlRIx5Y2LOkbzH8Mx3UHPlQYczqLbq1Qt'], 'chapter': ['2'], 'completed': ['on'], 'student': ['1']}> "

Я попробовал преобразовать все переменные, которые я использовал для идентификации пользователя, студента и главы, в их первичные ключи, но получил еще более сложную ошибку. Если есть более простой способ отслеживания прогресса или учебник по этому вопросу, пожалуйста, поделитесь.

Вот что я попробовал

Это модель StudemtProgress

class StudentProgress(models.Model):
    student = models.ForeignKey(
        Student, on_delete=models.CASCADE, related_name="student_progress"
    )
    chapter = models.ForeignKey(
        Chapter, on_delete=models.CASCADE, related_name="student_progress"
    )
    completed = models.BooleanField(default=False)

    

Это форма. Часть кода предназначена для выбора только текущего вошедшего пользователя и главы страницы, на которой она отображается.

class StudentProgressForm(forms.ModelForm):
    class Meta:
        model = StudentProgress
        fields = ("chapter", "completed", "student")
        # widgets = {
        #     "student": forms.HiddenInput(),
        # }

    def __init__(self, user, student_slug, chapter_slug, *args, **kwargs):
        super(StudentProgressForm, self).__init__(*args, **kwargs)
        student_queryset = Student.objects.filter(user=user, student_slug=student_slug)

        if student_queryset.exists():
            self.instance.student = student_queryset.first()
        else:
            self.instance.student = None

        if student_queryset.exists():
            self.fields["student"].initial = student_queryset.first()

        current_chapter = Chapter.objects.filter(chapter_slug=chapter_slug).first()
        self.fields["chapter"].initial = current_chapter

    def get_current_chapter(self, current_chapter_slug):
        return Chapter.objects.filter(chapter_slug=current_chapter_slug).first()

Эту логику я использовал в файле views.py

    if request.method == "POST":
        form = StudentProgressForm(
            request.POST,
            instance=single_chapter,
            student_slug=student_slug,
            chapter_slug=chapter_slug,
        )
        if form.is_valid():
            form.save()
            return redirect("user_dashboard")

    else:
        form = StudentProgressForm(
            user=request.user,
            instance=single_chapter,
            student_slug=student_slug,
            chapter_slug=chapter_slug,
        )

И, наконец, html-файл имеет такую форму

<form method="post">
      {% csrf_token %}
      {{ form.as_p }}
      <button type="submit">Submit</button>
    </form>

В файле views.py для POST-запроса при инициализации формы StudentProgressForm не указано поле user. Без указания поля user при обработке формы request.POST представляет QueryDict не пользователя, что приводит к ошибкам.

Вы можете решить эту проблему, изменив форму и представление следующим образом:

В форме StudentProgressForm:
def __init__(self, data, user, student_slug, chapter_slug, *args, **kwargs):
    super().__init__(data, *args, **kwargs)
Вид:
form = StudentProgressForm(
    data=request.POST,
    user=request.user
    instance=single_chapter,
    student_slug=student_slug,
    chapter_slug=chapter_slug,
)

Также, чтобы уменьшить количество лишних вопросов, можно попробовать следующее:

def __init__(self, data, user, student_slug, chapter_slug, *args, **kwargs):
    super().__init__(data, *args, **kwargs)
    student_queryset = Student.objects.filter(user=user, student_slug=student_slug)
    
    student = student_queryset.first() # 👈🏻 if  student not exists then default well be None
    self.instance.student = student
    self.fields["student"].initial = student

    current_chapter = Chapter.objects.filter(chapter_slug=chapter_slug).first()
    self.fields["chapter"].initial = current_chapter
Вернуться на верх