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