C O D E
C O D E

Reputation: 85

(DJANGO) NoReverseMatch at post/<slug:slug>

I'm trying to implement comments form in my Django Blog. I was going through this tutorial(https://djangocentral.com/creating-comments-system-with-django/), but there is an error happened in the end. The error page is saying:

NoReverseMatch at /post/firstpost/

Reverse for 'user-posts' with arguments '('',)' not found. 1 pattern(s) tried: ['user\/(?P[^/]+)$']

enter image description here

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>/', views.post_detail, 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"),
]

models.py

class Comment(models.Model):
    post = models.ForeignKey(Post,on_delete=models.CASCADE,related_name='comments')
    name = models.CharField(max_length=80)
    email = models.EmailField()
    body = models.TextField()
    created_on = models.DateTimeField(auto_now_add=True)
    active = models.BooleanField(default=False)

    class Meta:
        ordering = ['created_on']

    def __str__(self):
        return 'Comment {} by {}'.format(self.body, self.name)

forms.py

from .models import Comment
from django import forms

class CommentForm(forms.ModelForm):
    class Meta:
        model = Comment
        fields = ('name', 'email', 'body')

admin.py

from django.contrib import admin
from .models import Post, Category, Comment

class CategoryAdmin(admin.ModelAdmin):
    pass


@admin.register(Comment)
class CommentAdmin(admin.ModelAdmin):
    list_display = ('name', 'body', 'post', 'created_on', 'active')
    list_filter = ('active', 'created_on')
    search_fields = ('name', 'email', 'body')
    actions = ['approve_comments']

    def approve_comments(self, request, queryset):
        queryset.update(active=True)

admin.site.register(Post)
admin.site.register(Category, CategoryAdmin)

views.py

def post_detail(request, slug):
    template_name = 'blog/post_detail.html'
    post = get_object_or_404(Post, slug=slug)
    comments = post.comments.filter(active=True)
    new_comment = None
    # Comment posted
    if request.method == 'POST':
        comment_form = CommentForm(data=request.POST)
        if comment_form.is_valid():

            # Create Comment object but don't save to database yet
            new_comment = comment_form.save(commit=False)
            # Assign the current post to the comment
            new_comment.post = post
            # Save the comment to the database
            new_comment.save()
    else:
        comment_form = CommentForm()

    return render(request, template_name, {'post': post,
                                           'comments': comments,
                                           'new_comment': new_comment,
                                           'comment_form': comment_form})

post_detail.html

{% extends 'blog/base.html' %}
{% block content %}
  <article class="media content-section">
    <img class="rounded-circle article-img" src="{{ object.author.profile.image.url }}" alt="">
    <div class="article-metadata">
      <a class="mr-2 author_title" href="{% url 'user-posts' object.author.username %}">@{{ object.author }}</a>
      <small class="text-muted">{{ object.date_posted|date:"N d, Y" }}</small>

      <div>
        <!-- category section -->
        <small class="text-muted">
          Categories:&nbsp;
          {% for category in post.categories.all %}
          <a href="{% url 'blog_category' category.name %}">
            {{ category.name }}
          </a>&nbsp;
          {% endfor %}
        </small>
      </div>

      {% if object.author == user %}
        <div>
          <a class='btn btn-secondary btn-sm mt-1 mb-1' href="{% url 'post-update' object.slug %}">Update</a>
          <a class='btn btn-danger btn-sm mt-1 mb-1' href="{% url 'post-delete' object.slug %}">Delete</a>
        </div>
      {% endif %}
    </div>
  </article>
  <article class="media content-section">
    <div class="media-body">
      <img class="img-fluid center" id="rcorners3" src="{{ object.image.url }}" alt="none">
      <h2 class="article-title text-center">{{ object.title }}</h2>
      <p class="article-content">{{ object.content }}</p>
    </div>
  </article>
  <article class="media content-section">

    <div class="card-body">
       <!-- comments -->
       <h2>{{ comments.count }} comments</h2>

       {% for comment in comments %}
       <div class="comments" style="padding: 10px;">
         <p class="font-weight-bold">
           {{ comment.name }}
           <span class=" text-muted font-weight-normal">
             {{ comment.created_on }}
           </span>
         </p>
         {{ comment.body | linebreaks }}
       </div>
       {% endfor %}
     </div>
     <div class="col-md-8 card mb-4  mt-3 ">
       <div class="card-body">
         {% if new_comment %}
         <div class="alert alert-success" role="alert">
           Your comment is awaiting moderation
         </div>
         {% else %}
         <h3>Leave a comment</h3>
         <form method="post" style="margin-top: 1.3em;">
           {{ comment_form.as_p }}
           {% csrf_token %}
           <button type="submit" class="btn btn-primary  btn-lg">Submit</button>
         </form>
         {% endif %}
      </div>

    </article>
{% endblock content %}

Need help.

EDIT

The result after changing href="{% url 'user-posts' object.author.username %} to href="{% url 'user-posts' post.author.username %} (The post itself isn't displayed and I can't see author, but comment section works well.) enter image description here

Upvotes: 0

Views: 434

Answers (2)

schillingt
schillingt

Reputation: 13731

The problem is that your template, post_detail.html expects an instance called object, while your view post_detail is supplying the instance with the name post. Resolve these one way or the other and your problem should clear up.

Upvotes: 1

kamilyrb
kamilyrb

Reputation: 2627

In your urls.py definitions, use

path("user/<slug:username>", UserPostListView.as_view(), name='user-posts')

instead of

path("user/<str:username>", UserPostListView.as_view(), name='user-posts')

Depends on document:

  • str - Matches any non-empty string, excluding the path separator, '/'. This is the default if a converter isn’t included in the expression.
  • slug - Matches any slug string consisting of ASCII letters or numbers, plus the hyphen and underscore characters. For example, building-your-1st-django-site.

Upvotes: 1

Related Questions