简体   繁体   中英

How to fix this: Reverse for 'post_detail' with keyword arguments '{'slug': ''}' not found. 1 pattern(s) tried: ['(?P<slug>[-a-zA-Z0-9_]+)/$']?

From the error message it would appear to me that a dictionary variable is required: {'slug': ''}'. Even if this supposition is correct, I am not sure what variable is being sought nor where. Additional, possibly relevant data: this is based on the https://tutorial.djangogirls.org/en/ . Also attempting to include comments based onhttps://djangocentral.com/creating-comments-system-with-django/ and slugs based on https://medium.com/tech-insights/how-to-create-django-seo-friendly-url-using-slugs-fa2bbc098690 . Code to date:

Models.py

from django.conf import settings
from django.db import models
from django.utils import timezone
from django.contrib.auth.models import User
from django.urls import reverse
from django.utils.text import slugify

class PageSubject(models.Model):
    page_subject = models.CharField(max_length=200)
    
    class Meta:
        # Gives the proper plural name for class called subject
        verbose_name_plural = "Subjects"

    def __str__(self):
        return self.page_subject

class Post(models.Model):
    author = models.ForeignKey(User, default=1, on_delete=models.SET_DEFAULT, related_name='blog_posts')
    date_added = models.DateTimeField(auto_now_add=True)
    page_subject = models.ForeignKey(PageSubject, verbose_name='PageSubject', default=1, on_delete=models.SET_DEFAULT)   
    slug = models.SlugField(default='', editable=False, max_length=200, null = False)
    title = models.CharField(max_length=200, unique=True)
    content = models.TextField()
    def get_absolute_url(self):
        kwargs = {
            'slug': self.slug
        }
        return reverse('post_detail', kwargs=kwargs)
    def save(self, *args, **kwargs):
        value = self.title
        self.slug = slugify(value, allow_unicode=True)
        super().save(*args, **kwargs)
    
    class Meta:
        ordering = ['-date_added']
        
    def __str__(self):
        return self.title
        
class Comment(models.Model):
    post = models.ForeignKey(Post, default=1, on_delete=models.SET_DEFAULT, related_name='comments')
    name = models.CharField(max_length=80)
    email = models.EmailField()
    body = models.TextField()
    made_on = models.DateTimeField(auto_now_add=True)
    active = models.BooleanField(default=False)

    class Meta:
        ordering = ['made_on']

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

urls.py

from django.urls import path
from . import views

urlpatterns = [
    path('', views.index, name='index'),
    path('<slug:slug>/', views.post_detail, name='post_detail'),
    path('post/new/', views.post_new, name='post_new'),
]

views.py

from django.shortcuts import render, get_object_or_404, redirect
from django.utils import timezone
from django.views import generic
from .models import Post
from .forms import PostForm
Reverse for 'post_detail' with keyword arguments '{'slug': ''}' not found. 1 pattern(s) tried: ['(?P<slug>[-a-zA-Z0-9_]+)/$']
# Create your views here.

def index(request):
    posts = Post.objects.filter(date_added__lte=timezone.now()).order_by('-date_added')
    return render(request, 'blog/index.html', {'posts': posts})

def post_detail(request, slug):
    post = get_object_or_404(Post, slug=slug)
    return render(request, 'blog/post_detail.html', {'post': post})

def post_new(request):
    if request.method == "POST":
        form = PostForm(request.POST)
        if form.is_valid():
            post = form.save(commit=False)
            post.author = request.user
            post.date_added = timezone.now()
            post.save()
            return redirect('post_detail', slug=slug)
        
    else:
        form = PostForm()
    return render(request, 'blog/post_edit.html', {'form': form})

urls.py

from django.urls import path
from . import views

urlpatterns = [
    path('', views.index, name='index'),
    path('<slug:slug>/', views.post_detail, name='post_detail'),
    path('post/new/', views.post_new, name='post_new'),
]

base.html

{% load static %}
<html>
    <head>
        <title>drsmart.info</title>    
    </head>
    <body>
        <h1>DR SMART.INFO</h1>
        <p>the web site for the analytical rugby fan</p>
    {% block content %}
    {% endblock %}
    </body>
</html>

index.html

{% extends 'blog/base.html' %}

{% block content %}
    {% for post in posts %}
        <div>
            <h2><a href="{% url 'post_detail' slug=post.slug %}">{{ post.title }}</a></h2>
            <p>author: {{post.author}}, published: {{post.date_added }}</p>
            <p>{{ post.content|linebreaksbr }}</p>
        </div>
    {% endfor %}
{% endblock %}

post_detail.html

{% extends 'blog/base.html' %}

{% block content %}
    <div class="post">
        {% if post.date_added %}
            <div class="date">
                {{ post.date_added }}
            </div>
        {% endif %}
        <h2>{{ post.title }}</h2>
        <p>{{ post.content|linebreaksbr }}</p>
    </div>{% extends 'blog/base.html' %}

{% block content %}
    <div class="post">
        {% if post.date_added %}
            <div class="date">
                {{ post.date_added }}
            </div>
        {% endif %}
        <h2>{{ post.title }}</h2>
        <p>{{ post.content|linebreaksbr }}</p>
    </div>
{% endblock %}

{% endblock %}

After lengthy toil, your suggested improvements will be greatly appreciated, Roderic.

ok in it is recommended to have a sth before your str in your url (expect the home page or indext that shows the main page in website)

so change your url.py to this:

urlpatterns = [
path('', views.index, name='index'),
path('post-detial/<str:slug>/', views.post_detail, name='post_detail'),
path('post/new/', views.post_new, name='post_new'),

]

note that passing put str for slug while passing variables.

and in your template if you omit the slug= since you have one variable to pass and if you have more better to just do it by order. nothing

 <h2><a href="{% url 'post_detail' post.slug %}">{{ post.title }}</a></h2>

note: while setting urls, you should have a main url like you have for path('post/new/', views.post_new, name='post_new') it make the code more practical.

Correct your slug field to --> unique=True and remove default

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM