Home > Blockchain >  DJANGO: NOT NULL constraint failed: courses_comment.lesson_id
DJANGO: NOT NULL constraint failed: courses_comment.lesson_id

Time:07-24

I try create comments form add and take error. But I'm not shure that I correctly use lesson = at view.py at def post function. Can You help me?

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()

part of 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 >
    <form method="post">
    {% csrf_token %}
    {{ form }}
    <button type="submit">ОК</button>
</div>

And my Error

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

CodePudding user response:

My suspicion is that this is causing your issue:

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

What this is doing is returning the first Lesson object in a queryset filtered by your lesson slug. However, filter will return an empty queryset if there are no results. Running first() on that empty queryset will return nothing, which would explain why an ID is not being passed to your form.

To solve this, you just need to catch whether the lesson object is empty:

if lesson is None:
   # do something else

As an aside, combining .filter() and .first() is generally not recommended as you are potentially being vague with your object selection. Using .get() will get you a single object and return an error if two or more are returned. The downside with .get() is that it will also raise an exception if nothing is returned, so you need to handle both outcomes in your view.

CodePudding user response:

May be not best solution but It's work:

    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()
  • Related