adrq
adrq

Reputation: 69

Form is not displaying

I have 2 views, DetailView is displaying the post data and CreateView is creating comment to this post. The problem is my template isnt rendering any comment form and theres no error in my console and I have no idea why this is not working. Am i doing something wrong? If yes, Can I implement this differently? If yes, what should I use? Thank you in advance :)

views code:

class PostDetailView(LoginRequiredMixin, DetailView):
    model = Post
    context_object_name = 'post'
    template_name = 'post/details.html'


class CommentCreate(LoginRequiredMixin, CreateView):
    model = Comment
    form_class = CommentCreationForm
    context_object_name = 'forma'
    template_name = 'post/details.html'

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

details.html template code:

{% extends 'base.html' %}
{% load static %}

{% block content %}
    <h1>POST</h1>
    {{ post.content }}
    <hr>
    <form action="" method="post">
        {% csrf_token %}
        {{ form }}
        <button class="btn btn-default" type="submit">Comment</button>

    </form>
{% endblock content %}

comment form:

class CommentCreationForm(forms.ModelForm):
    class Meta:
        model = Comment
        fields = ('text', )

comment model:

class Comment(models.Model):
    author = models.ForeignKey(User, on_delete=models.CASCADE)
    post = models.ForeignKey(Post, on_delete=models.CASCADE)

    text = models.TextField()
    date_posted = models.DateTimeField(auto_now_add=True)

    def __str__(self):
        return str(self.id)

Upvotes: 1

Views: 68

Answers (2)

Ali_Sheikhi
Ali_Sheikhi

Reputation: 96

I usually do it by functions instead class

this is my sample code:

views.py: (after all post views)

@login_required
def add_comment_to_post(request ,pk):
    post = get_object_or_404(Post,pk=pk)
    if request.method == 'POST':
        form = CommentForm(request.POST)
        if form.is_valid():
            comment = form.save(commit=False)
            comment.post = post
            comment.save()
            return redirect('post_detail',pk=post.pk)
    else:
        form = CommentForm()
    return render(request,'blog/comment_form.html',{'form':form})


@login_required
def comment_approve(request,pk):
    comment = get_object_or_404(Comment,pk=pk)
    comment.approve()
    return redirect('post_detail',pk=comment.post.pk)


@login_required
def comment_remove(request,pk):
    comment = get_object_or_404(Comment,pk = pk)
    post_pk = comment.post.pk
    comment.delete()
    return redirect('post_detail',pk=post_pk)

models.py:

class Post(models.Model):
    author = models.ForeignKey('auth.User',on_delete=models.CASCADE)
    title = models.CharField(max_length = 50)
    text = models.CharField(max_length=500)
    created_date = models.DateTimeField(default=timezone.now)
    published_date = models.DateTimeField(blank=True, null=True)

    def publish(self):
        self.published_time = timezone.now()
        self.save()

    def approve_comments(self):
        return self.comments.filter(approved_comment=True)


    def get_absolute_url(self):
        return reverse("post_detail",kwargs={'pk':self.pk})


    def __str__(self):
        return self.title




class Comment(models.Model):       

 post=
models.ForeignKey('blog.Post',related_name='comments',on_delete=models.CASCAD)
    author = models.CharField(max_length=16)
    text = models.CharField(max_length=220)
    created_date = models.DateTimeField(default=timezone.now)
    approved_comment = models.BooleanField(default=False)

    def approve(self):
        self.approved_comment = True
        self.save()

    def get_absolute_url(self):
        return reverse('post_list')

    def __str__(self):
        return self.text

Upvotes: 0

willeM_ Van Onsem
willeM_ Van Onsem

Reputation: 477641

If you make a request, you always will end up triggering one view. That view can render, zero, one or more templates to generate a HTTP response, but it does not need any templates at all. Template are only a mechanism to make it more convenient to generate HTML.

If you thus make a request to the DetailView, then this will not somehow include the CreateView, it will simply let the DetailView decide what should be done to generate a response and in this case that is rendering a template.

You can however easily use the FormMixin [Django-doc] to render the form:

from django.views.generic.edit import FormMixin

class PostDetailView(FormMixin, LoginRequiredMixin, DetailView):
    model = Post
    form_class = CommentCreationForm
    context_object_name = 'post'
    template_name = 'post/details.html'

    def post(self, request, *args, **kwargs):
        form = self.get_form()
        self.object = self.get_object()
        if form.is_valid():
            return self.form_valid(form)
        else:
            return self.form_invalid(form)

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

Here we thus make use of the mixin to handle the logic to create a form and pass it to the context. We have to implement the post method that will check if the form is valid, and if it is, adds the author and the post to the instance wrapped in the form.


Note: It is normally better to make use of the settings.AUTH_USER_MODEL [Django-doc] to refer to the user model, than to use the User model [Django-doc] directly. For more information you can see the referencing the User model section of the documentation.

Upvotes: 1

Related Questions