djangoformsdetailview

In Django how to initialize a form with the current detailview object?


I'm a Django beginner building a blog Website.

The models are: Blog, Threads, Comments. The Blog has Threads, each Thread has Comments.

From the Thread detailview the logged user can create a comment with a form. The created Comment should have its 'thread' value initialized with the current detailview thread object, as thread is a foreignkey to the Thread model in the Comment model.

In the Comment create view, I tried to use form.instance.thread = self.kwargs['pk'] but it brings this error: KeyError at /blogs/comment/create/ 'pk'.

Can you please help me to pass the thread to the form?

models.py:

class Comment(models.Model):
    comment_date = models.DateField(default=datetime.date.today, blank=True)
    comment_text = models.TextField(max_length=1000, help_text='Enter your comment')
    user = models.ForeignKey(User, on_delete=models.CASCADE, null=True)    
    thread = models.ForeignKey('Thread', on_delete=models.SET_NULL, null=True)
    class Meta:
        verbose_name = 'comment'
        verbose_name_plural = 'comments'           
    def __str__(self):
        return f'{self.id} ({self.thread.thread_name})'
    def get_absolute_url(self):      
        return reverse('comment-detail', args=[str(self.id)])

class Thread(models.Model):
    thread_name = models.CharField(max_length=200)
    user = models.ForeignKey(User, on_delete=models.CASCADE, null=True)
    summary = models.TextField(max_length=1000,)
    post_date = models.DateField(null=True, blank=True)    
    blog = models.ForeignKey('Blog', on_delete=models.CASCADE, null=True)    
    class Meta:
        ordering = ['-post_date']
    def __str__(self):
        return self.thread_name
    def get_absolute_url(self):
        return reverse('thread-detail', args=[str(self.id)])

urls.py:

path('thread/<int:pk>/', views.ThreadDetailView.as_view(), name='thread-detail')
path('comment/create/', views.CommentCreate.as_view(), name='comment_create')

views.py:

class ThreadDetailView(generic.DetailView):
    model = Thread


class CommentCreate(LoginRequiredMixin, CreateView):   
    model = Comment
    fields = ['comment_text', 'thread']     
  
    def form_valid(self, form):
        form.instance.user = self.request.user
        form.instance.thread = self.kwargs['pk'] # This doesn't work
        return super(CommentCreate, self).form_valid(form)

Solution

  • I finally found another way to solve the problem:

       <a href="{% url 'comment_create' thread.pk %}">  Create a New Comment</a>