Есть ли способ обойти проблему "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