Django UpdateView doesn't save a new value
I have a forum app, its structure is "forum-subforum-topic-comment". Topics are exclusive for their subforum, comments are exclusive for their topic and displayed only inside the topic. Views are implemented mostly via class-based-views.
While creating a new Topic
, you have to define not only the field subject
, but also the initial comment, first_comment
. It is pretty similar to objects of the Comment
model, but is effectively a part of the Topic
model.
So, the problem is that while my UpdateView for comments (UpdateComment
) works well, and comments are edited without any issues, the UpdateView for a first_comment
of Topic
objects, though returning no error, doesn't edit the field (the page is rendered, it works, the terminal even shows some amount of data near the code 200 - but the content of the field stays the same).
And that's sad. You know it's very sad, when you do it the way it must work, it seems like it must work, you waste lots of time to make it work, but it refuses to work by any reason.
models.py (Topic and Comment models only):
class Topic(models.Model):
subject = models.CharField(verbose_name='Заголовок', max_length=255, unique=True)
first_comment = models.TextField(verbose_name='Сообщение', max_length=2000, default='')
slug = models.SlugField(default='', unique=True, max_length=25, editable=False)
subforum = models.ForeignKey('Subforum', verbose_name='Раздел',
on_delete=models.CASCADE, related_name='subforum')
creator = models.ForeignKey(User, verbose_name='Создатель темы',
on_delete=models.SET('deleted'), related_name='creator')
created = models.DateTimeField(auto_now_add=True)
closed = models.BooleanField(default=False)
objects = models.Manager()
class Meta:
ordering = ['id']
verbose_name = 'Обсуждения'
verbose_name_plural = 'Обсуждения'
def __str__(self):
return self.subject
def save(self, *args, **kwargs):
if not self.id:
self.slug = f'topic-{slugify(self.subject)}'
return super(Topic, self).save(*args, **kwargs)
def get_absolute_url(self):
return reverse('forum:topic', kwargs={'topic_slug': self.slug, 'subforum_slug': self.subforum.slug})
class Comment(models.Model):
topic = models.ForeignKey('Topic', verbose_name='Тема', on_delete=models.CASCADE,
related_name='comments')
author = models.ForeignKey(User, verbose_name='Комментатор',
on_delete=models.SET('deleted'), related_name='author')
content = models.TextField(verbose_name='Текст', max_length=2000)
created = models.DateTimeField(verbose_name='Дата публикации', auto_now_add=True)
updated = models.DateTimeField(verbose_name='Дата изменения', auto_now=True)
objects = models.Manager()
class Meta:
ordering = ['created']
verbose_name = 'Комментарии'
verbose_name_plural = 'Комментарии'
def __str__(self):
return f'Post of {self.topic.subject} is posted by {self.author.username}.'
views.py (ShowTopic, AddTopic, UpdateFirstComment and UpdateComment for comparison):
class ShowTopic(DetailView):
model = Topic
template_name = "forum/topic.html"
slug_url_kwarg = 'topic_slug'
context_object_name = 'topic'
paginate_by = 5
def get_context_data(self, **kwargs):
context = super().get_context_data(**kwargs)
topic = self.get_object()
comments_list = Comment.objects.filter(topic=topic).order_by('created')
paginator = Paginator(comments_list, self.paginate_by)
page_number = self.request.GET.get('page', 1)
page_obj = paginator.get_page(page_number)
context.update({
'menu': menu,
'comments': page_obj,
'page_obj': page_obj,
'is_paginated': page_obj.has_other_pages(),
'paginator': paginator,
'comm_num': comments_list.count(),
})
return context
class AddTopic(LoginRequiredMixin, DataMixin, CreateView):
form_class = AddTopicForm
template_name = 'forum/addtopic.html'
page_title = 'Create a new topic'
def get_success_url(self):
return reverse('forum:topic', kwargs={
'subforum_slug': self.kwargs['subforum_slug'], 'topic_slug': self.object.slug})
def form_valid(self, form):
subforum = Subforum.objects.get(slug=self.kwargs['subforum_slug'])
form.instance.creator = self.request.user
form.instance.subforum = subforum
return super(AddTopic, self).form_valid(form)
class AddComment(LoginRequiredMixin, DataMixin, CreateView):
model = Comment
form_class = AddCommentForm
template_name = 'forum/addcomment.html'
page_title = 'Leave a comment'
def get_success_url(self):
return reverse('forum:topic', kwargs={
'subforum_slug': self.kwargs['subforum_slug'],
'topic_slug': self.kwargs['topic_slug']})
def form_valid(self, form):
topic = Topic.objects.get(slug=self.kwargs['topic_slug'])
form.instance.author = self.request.user
form.instance.topic = topic
return super(AddComment, self).form_valid(form)
class UpdateFirstComment(LoginRequiredMixin, DataMixin, UpdateView):
model = Topic
form_class = AddTopicForm
template_name = 'forum/editcomment.html'
page_title = 'Edit comment'
def get_success_url(self):
return reverse('forum:topic', kwargs={
'subforum_slug': self.kwargs['subforum_slug'],
'topic_slug': self.kwargs['topic_slug']
})
def get_object(self, queryset=None):
return Topic.objects.get(slug=self.kwargs['topic_slug'], subforum__slug=self.kwargs['subforum_slug'])
def form_valid(self, form):
topic = self.get_object()
first_comment = topic.first_comment
form.instance.creator = self.request.user
form.instance.topic = topic
form.instance.first_comment = first_comment
return super(UpdateFirstComment, self).form_valid(form)
class UpdateComment(LoginRequiredMixin, DataMixin, UpdateView):
model = Comment
form_class = AddCommentForm
context_object_name = 'comment'
template_name = 'forum/editcomment.html'
page_title = 'Edit comment'
def get_success_url(self):
return reverse('forum:topic', kwargs={
'subforum_slug': self.kwargs['subforum_slug'],
'topic_slug': self.kwargs['topic_slug']
})
urls.py
app_name = 'forum'
urlpatterns = [
path('', SubForumListView.as_view(), name='forum'),
path('<slug:subforum_slug>/', TopicListView.as_view(), name='subforum'),
path('<slug:subforum_slug>/add_topic/', AddTopic.as_view(), name="add_topic"),
path('<slug:subforum_slug>/topics/<slug:topic_slug>/', ShowTopic.as_view(), name='topic'),
path('<slug:subforum_slug>/topics/<slug:topic_slug>/edit_topic/', UpdateFirstComment.as_view(), name='edit_topic'),
path('<slug:subforum_slug>/topics/<slug:topic_slug>/add_comment/', AddComment.as_view(), name="add_comment"),
path('<slug:subforum_slug>/topics/<slug:topic_slug>/<int:pk>/edit_comment/', UpdateComment.as_view(), name="edit_comment"),
path('<slug:subforum_slug>/topics/<slug:topic_slug>/<int:pk>/delete_comment/', DeleteComment.as_view(), name="delete_comment"),
]
If something else is necessary to understand the context better, please inform me.