mr_bobby
mr_bobby

Reputation: 11

Django prepopulate form in UpdateView

Would like to know if it's possible to prepopulate my CommentForm in UpdateView. Updating comments work's except that the form is not loaded prepopulated.

When testing using a separate template it's loaded prepopulated, but I would like to use the same template (PostDetail) using a modal to update the comment.

views.py:

class PostDetail(View):

    def get(self, request, slug, pk, *args, **kwargs):

        queryset = Post.objects.all()
        post = get_object_or_404(queryset,slug=slug, pk=pk)
        comments = post.comments.order_by('-created_on')

        return render(
            request,
            'blog/post_detail.html',
            {
                'post': post,
                'comments': comments,
                'comment_form': CommentForm()
            },
        )

    def post(self, request, slug, pk, *args, **kwargs):

        if request.user.is_authenticated:
            queryset = Post.objects.all()
            post = get_object_or_404(queryset, slug=slug, pk=pk)
            comment_form = CommentForm(data=request.POST)

            if comment_form.is_valid():
                comment = comment_form.save(commit=False)
                comment.post = post
                comment.author = request.user
                comment.save()
                messages.info(request, 'Comment added')

        return HttpResponseRedirect(reverse('post_detail', args=[slug, pk]))


class CommentUpdate(LoginRequiredMixin, UserPassesTestMixin, generic.UpdateView):
    
    model = Comment
    template_name = 'blog/post_detail.html'
    form_class = CommentForm
 
    def get_success_url(self):
        post = Post.objects.get(pk=self.object.post.pk)
        messages.info(self.request, 'Comment updated')
        return post.get_absolute_url()

    def form_valid(self, form):
        form.instance.author = self.request.user
        return super().form_valid(form)

    def test_func(self):
        comment = self.get_object()
        if self.request.user == comment.author:
            return True
        return False`

forms.py:

class CommentForm(forms.ModelForm):

    class Meta:
        model = Comment
        fields = ('body',)

post_detail.html (form):

<form action="{% url 'comment_update' post.slug comment.pk %}" method="POST">
  {% csrf_token %}
  {{ comment_form | crispy }}                         
  <button type="submit" class="btn">Update</button>
</form>

Please need help :)

I have tested adding:

def get_form_kwargs(self):
    kwargs = super().get_form_kwargs()
    kwargs['instance'] = self.get_object()
    return kwargs

The form is still not prepopulated. It works if I use a separate template and render the form using {{ form | crispy }}.

Perhaps it's because I have two {{ comment_form | crispy }} in my post_detail.html, one when creating the comment and one to update it?

I've spend alot of time trying to figure this out :)

Upvotes: 1

Views: 335

Answers (1)

Sunderam Dubey
Sunderam Dubey

Reputation: 8837

You can pass that instance of the Comment model which you'd like to update in CommetForm. In the get_form_kwargs() method, you can add the instance keyword argument to the form kwargs with the instance of the Comment model to update. Then, the CommentForm will be pre-populated with the data from that instance while displaying in frontend so:

class CommentUpdate(LoginRequiredMixin, UserPassesTestMixin, generic.UpdateView):
    
    model = Comment
    template_name = 'blog/post_detail.html'
    form_class = CommentForm
 
    def get_success_url(self):
        post = Post.objects.get(pk=self.object.post.pk)
        messages.info(self.request, 'Comment updated')
        return post.get_absolute_url()

    def form_valid(self, form):
        form.instance.author = self.request.user
        return super().form_valid(form)

    def get_form_kwargs(self):
        kwargs = super().get_form_kwargs()
        kwargs['instance'] = self.get_object()
        return kwargs

    def test_func(self):
        comment = self.get_object()
        if self.request.user == comment.author:
            return True
        return False

Upvotes: 1

Related Questions