C O D E
C O D E

Reputation: 85

Can't add comment form in Django web application

I have a trouble adding form-group (I believe it's bootstrap class). The form-group doesn't do anything at all, or maybe it's a problem with form.author and form-body variables!?

More simply, I need UI comment section (now only I can add and edit comments from django admin page). Some code:

post_details.html

<article class="media content-section">

      <form action="/post/{{ post.slug }}/" method="post">

          {% csrf_token %}

          <div class="form-group">

              {{ form.author }}

          </div>

          <div class="form-group">

              {{ form.body }}

          </div>

          <button type="submit" class="btn btn-primary">Submit</button>

      </form>

       <ul>
       {% for comment in post.comments.all %}
        <p>
          <b>@{{ comment.author }}</b>
          <small>{{ comment.created_date }} </small>
        </p>
        <p>    {{ comment.text }}</p>
        <hr>
        {% if comment.replies.all %}
        <ul>
          {% for reply in comment.replies.all %}
            <p>{{ reply.text }}</p>
            <hr>
          {% endfor %}
         </ul>
         {% endif %}
        {% endfor %}
       <ul>

    </article>

forms.py

from django import forms

class CommentForm(forms.Form):
    author = forms.CharField(
        max_length=60,
        widget=forms.TextInput(
            attrs={"class": "form-control", "placeholder": "Your Name"}
        ),
    )
    body = forms.CharField(
        widget=forms.Textarea(
            attrs={"class": "form-control", "placeholder": "Leave a comment!"}
        )
    )

views.py

def comment(request):

    form = CommentForm()
    if request.method == "POST":
        form = CommentForm(request.POST)
        if form.is_valid():
            comment = Comment(
                author=form.cleaned_data["author"],
                body=form.cleaned_data["body"],
                post=post,
            )
            comment.save()

    context = {"post": post, "comments": comments, "form": form}

    if request.method == 'POST':
        form = CommentForm(request.POST)
        if form.is_valid():
            comment = Comment(
                author=form.cleaned_data["author"],
                body=form.cleaned_data["body"],
                post=post
            )
            comment.save()

    comments = Comment.objects.filter(post=post)
    context = {
        "post": post,
        "comments": comments,
        "form": form,
    }

models.py

class Comment(models.Model):
    post = models.ForeignKey(Post, on_delete=models.CASCADE, related_name='comments')
    author = models.ForeignKey(User, on_delete=models.CASCADE)
    text = models.TextField()
    created_date = models.DateField(auto_now_add=True)

    def __str__(self):
        return self.text

EDIT:

urls.py

from django.urls import path
from django.conf.urls import include, url
from . import views
from .views import PostListView, PostDetailView, PostCreateView, PostUpdateView, PostDeleteView, UserPostListView

urlpatterns = [
    #Blog section
    path("", PostListView.as_view(), name='blog-home'),
    path("user/<str:username>", UserPostListView.as_view(), name='user-posts'),
    path('post/<slug:slug>/', PostDetailView.as_view(), name='post-detail'),
    path("posts/new/", PostCreateView.as_view(), name='post-create'),
    path("post/<slug:slug>/update/", PostUpdateView.as_view(), name='post-update'),
    path("post/<slug:slug>/delete/", PostDeleteView.as_view(), name='post-delete'),
    path("about/", views.about, name="blog-about"),
    path("<category>/", views.blog_category, name="blog_category"),
]

I really need something like this (tried to follow this tutorial, but nothing works well :enter image description here

My comment section:

enter image description here

Upvotes: 0

Views: 171

Answers (3)

Eliakin Costa
Eliakin Costa

Reputation: 960

I've looked into that tutorial and implemented myself. Here goes the answer:

urls.py

from django.urls import path
from . import views

urlpatterns = [
    path("", views.blog_index, name="blog_index"),
    path("<slug:slug>/", views.post_detail, name="post_detail"),
    path("<category>/", views.blog_category, name="blog_category"),
]

models.py

from django.db import models
from django.utils.text import slugify

class Category(models.Model):
    name = models.CharField(max_length=20)


class Post(models.Model):
    title = models.CharField(max_length=255)
    body = models.TextField()
    created_on = models.DateTimeField(auto_now_add=True)
    last_modified = models.DateTimeField(auto_now=True)
    categories = models.ManyToManyField("Category", related_name="posts")
    slug = models.SlugField(unique=True)

    def save(self, *args, **kwargs):
        self.slug = slugify(self.title)
        super(Post, self).save(*args, **kwargs)


class Comment(models.Model):
    author = models.CharField(max_length=60)
    body = models.TextField()
    created_on = models.DateTimeField(auto_now_add=True)
    post = models.ForeignKey("Post", on_delete=models.CASCADE)

post_detail.html

{% extends "blog_app/base.html" %}
{% block page_content %}
<div class="col-md-8 offset-md-2">
    <h1>{{ post.title }}</h1>
    <small>
        {{ post.created_on.date }} |&nbsp;
        Categories:&nbsp;
        {% for category in post.categories.all %}
        <a href="{% url 'blog_category' category.name %}">
            {{ category.name }}
        </a>&nbsp;
        {% endfor %}
    </small>
    <p>{{ post.body | linebreaks }}</p>
    <h3>Leave a comment:</h3>
    <form action="/blog/{{ post.pk }}/" method="post">
        {% csrf_token %}
        <div class="form-group">
            {{ form.author }}
        </div>
        <div class="form-group">
            {{ form.body }}
        </div>
        <button type="submit" class="btn btn-primary">Submit</button>
    </form>
    <h3>Comments:</h3>
    {% for comment in comments %}
    <p>
        On {{comment.created_on.date }}&nbsp;
        <b>{{ comment.author }}</b> wrote:
    </p>
    <p>{{ comment.body }}</p>
    <hr>
    {% endfor %}
</div>
{% endblock %}

views.py

def post_detail(request, slug):
    post = Post.objects.get(slug=slug)
    comments = Comment.objects.filter(post=post)

    form = CommentForm()
    if request.method == "POST":
        form = CommentForm(request.POST)
        if form.is_valid():
            comment = Comment(
                author=form.cleaned_data["author"],
                body=form.cleaned_data["body"],
                post=post,
            )
            comment.save()

    context = {"post": post, "comments": comments, "form": form}
    return render(request, "blog_app/post_detail.html", context)

Edit

I've changed the code to support slug field generation from the title. I'm not handling exception, thus you gonna have look into it by yourself. Good luck.

Upvotes: 1

St&#233;phane
St&#233;phane

Reputation: 132

In your file views.py you have duplicated code and you don't have the return statement:

return render(request, "post_details.html", context)

Upvotes: 1

schillingt
schillingt

Reputation: 13731

I think the problem is you're using a Form and not a ModelForm.

class CommentForm(forms.ModelForm):
    class Meta:
        model = Comment
        fields = ['author', 'text']
    ...

Upvotes: 1

Related Questions