DJANGO: Сбой ограничения NOT NULL: courses_comment.lesson_id

Я пытаюсь создать форму комментариев добавить и принять ошибку. Но я не уверен, что правильно использую lesson = в view.py в def post функции. Вы можете мне помочь?

models.py:

class Comment(models.Model):
text = models.TextField('Comment text')
user = models.ForeignKey(User, on_delete=models.CASCADE)
lesson = models.ForeignKey(Lesson, on_delete=models.CASCADE)

view.py:

class LessonDetailPage(DetailView):
....
    def post(self, request, *args, **kwargs):

        lesson = Lesson.objects.filter(slug=self.kwargs['lesson_slug']).first()
    
        post = request.POST.copy()
        post['user'] = request.user
        post['lesson'] = lesson
        request.POST = post
    
        form = CommentForms(request.POST)
        if form.is_valid():
           form.save()

часть urls.py

path('course/<slug>/<lesson_slug>', views.LessonDetailPage.as_view(), name='lesson-detail'),

forms.py:

class CommentForms(forms.ModelForm):

text = forms.CharField(
    label='Text',
    required=True,
    widget=forms.Textarea(attrs={'class': 'form-control'})
)
user = forms.CharField(
    widget=forms.HiddenInput()
)
lesson = forms.CharField(
    widget=forms.HiddenInput()
)

class Meta:
    model = Comment
    fields = ['text']

comment.html

<div class="form-section">
    <form method="post">
    {% csrf_token %}
    {{ form }}
    <button type="submit">ОК</button>
</div>

И моя ошибка

IntegrityError at /course/linux/set-on-linux
NOT NULL constraint failed: courses_comment.lesson_id
Request Method: POST
Request URL:    http://127.0.0.1:8000/course/linux/set-on-linux
Django Version: 4.0.6
Exception Type: IntegrityError
Exception Value:    
NOT NULL constraint failed: courses_comment.lesson_id

Мое подозрение, что это вызывает вашу проблему:

lesson = Lesson.objects.filter(slug=self.kwargs['lesson_slug']).first()

В результате возвращается первый объект Lesson в наборе запросов, отфильтрованном по слову lesson. Однако фильтр вернет пустой набор запросов, если в нем нет результатов. Выполнение first() на этом пустом наборе запросов ничего не вернет, что объясняет, почему ID не передается в вашу форму.

Чтобы решить эту проблему, нужно просто перехватить, является ли объект lesson пустым:

if lesson is None:
   # do something else

Кроме того, комбинирование .filter() и .first() обычно не рекомендуется, так как вы можете быть нечеткими при выборе объекта. Использование .get() даст вам один объект и вернет ошибку, если будет возвращено два или более. Недостатком .get() является то, что он также вызовет исключение, если ничего не будет возвращено, поэтому вам необходимо обработать оба результата в вашем представлении.

Может быть не лучшее решение, но оно работает:

    def post(self, request, *args, **kwargs):
    lesson = Lesson.objects.filter(slug=self.kwargs['lesson_slug']).first()
    post = request.POST.copy()
    post['user'] = request.user
    post['lesson'] = lesson
    request.POST = post
    
    form = CommentForms(request.POST)
    if form.is_valid():

        comment = Comment(text=request.POST['text'], user=request.POST['user'], lesson=request.POST['lesson'])
        comment.save()

Но лучше в forms.py написать:

class CommentForms(forms.ModelForm):
class Meta:
    model = Comment
    fields = ['text', 'user', 'lesson'] #here is the answer
    widgets = {'user': forms.HiddenInput(), 'lesson': forms.HiddenInput()}

then at views.py:

def post(self, request, *args, **kwargs):
    course = Course.objects.filter(slug=self.kwargs['slug']).first()
    lesson = Lesson.objects.filter(slug=self.kwargs['lesson_slug']).first()
    post = request.POST.copy()
    post['user'] = request.user
    post['lesson'] = lesson
    request.POST = post

    form = CommentForms(request.POST)
    if form.is_valid():
        form.save()
Вернуться на верх