【问题标题】:Reverse for 'detail' with keyword arguments '{'id': 5}' not found. 1 pattern(s) tried: ['posts/(?P<slug>[\\w-]+)/$']找不到关键字参数“{'id': 5}”的“详细信息”。尝试了 1 种模式:['posts/(?P<slug>[\\w-]+)/$']
【发布时间】:2017-08-23 17:51:06
【问题描述】:

我在 /posts/ 错误时非常卡住 NoReverseMatch。也许我忽略了一些小问题,或者这个问题比我正在挖掘的地方要大得多。

http://imgur.com/nlyMi9V models.py 时的错误信息如下:

def get_absolute_url(self):
        #return reverse("detail", kwargs={ "slug": self.slug })
        return reverse("posts:detail", kwargs={ "slug": self.slug })

http://imgur.com/a/RilrB models.py 时的错误信息如下:

def get_absolute_url(self):
        return reverse("detail", kwargs={ "slug": self.slug })
        #return reverse("posts:detail", kwargs={ "slug": self.slug })

models.py

#from _future_ import __unicode__literals
from django.db import models
from django.core.urlresolvers import reverse
from django.db.models.signals import pre_save

from django.utils.text import slugify

# Create your models here.
# MVC Models Views Controller

def upload_location(instance, filename):
    # filebase, extension = filename.spilt(".")
    # return "%s/%s.%s" %(instance.id, instance.id, filename)
    return "%s/%s" %(instance.id, filename)

class Post(models.Model):
    title = models.CharField(max_length=120)
    slug = models.SlugField(unique=True)
    image = models.ImageField(upload_to=upload_location, 
        null=True, 
        blank=True, 
        width_field="width_field", 
        height_field="height_field")
    height_field = models.IntegerField(default=0)
    width_field = models.IntegerField(default=0)
    content = models.TextField()
    updated = models.DateTimeField(auto_now=True, auto_now_add=False)
    timestamp = models.DateTimeField(auto_now=False, auto_now_add=True)

    def __unicode__(self):
        return self.title

    def __str__(self):
        return self.title

    def get_absolute_url(self):
        #return reverse("detail", kwargs={ "slug": self.slug })
        return reverse("posts:detail", kwargs={ "slug": self.slug })

    class Meta:
        ordering = ["-timestamp", "-updated"]


def create_slug(instance, new_slug=None):
    slug = slugify(instance.title)
    if new_slug is not None:
        slug = new_slug
    qs = Post.objects.filter(slug=slug).order_by("-id")
    exists = qs.exists()
    if exists:
        new_slug = "%s-%s" %(slug, qs.first().id)
        return create_slug(instance, new_slug=new_slug)
    return slug

def pre_save_post_receiver(sender, instance, *args, **kwargs):
    if not instance.slug:
        instance.slug = create_slug(instance)

pre_save.connect(pre_save_post_receiver, sender=Post)

views.py

from django.contrib import messages
from django.core.paginator import Paginator, EmptyPage, PageNotAnInteger
from django.http import HttpResponse, HttpResponseRedirect
from django.shortcuts import render, get_object_or_404, redirect

from .forms import PostForm
# Create your views here.
from .models import Post


def post_create(request):
    form = PostForm(request.POST or None, request.FILES or None,)
    if form.is_valid():
        instance = form.save(commit=False)
        instance.save()
        # message success
        messages.success(request, "Successfully Created!")
        return HttpResponseRedirect(instance.get_absolute_url())
    context = {
        "form": form,
    }
    return render(request, "post_form.html", context)

def post_detail(request, slug=None):
    #instant = Post.objects.get(id=0)
    instance = get_object_or_404(Post, slug=slug)
    context = {
        "title": instance.title,
        "instance": instance,
    }
    return render(request, "post_detail.html", context)

def post_list(request):
    queryset_list = Post.objects.all() #.order_by("-timestamp")
    paginator = Paginator(queryset_list, 5) # Show 5 contacts per page
    page_request_var = "page"
    page = request.GET.get(page_request_var)
    try:
        queryset = paginator.page(page)
    except PageNotAnInteger:
        # If page is not an integer, deliver first page.
        queryset = paginator.page(1)
    except EmptyPage:
        # If page is out of range (e.g. 9999), deliver last page of results.
        queryset = paginator.page(paginator.num_pages)

    context = {
        "object_list": queryset,
        "title": "List",
        "page_request_var": page_request_var
        }
    return render(request, "post_list.html", context)
    #return HttpResponse("<h1>List</h1>")


def post_update(request, slug=None):
    instance = get_object_or_404(Post, slug=slug)
    form = PostForm(request.POST or None, request.FILES or None, instance=instance)
    if form.is_valid():
        instance = form.save(commit=False)
        instance.save()
        # message success
        messages.success(request, "<a href='#'>Item</a> Saved", extra_tags='html_safe')
        return HttpResponseRedirect(instance.get_absolute_url())

    context = {
        "title": instance.title,
        "instance": instance,
        "form":form,
    }
    return render(request, "post_form.html", context)   

def post_delete(request, slug=None):
    instance = get_object_or_404(Post, slug=slug)
    instance.delete()
    messages.success(request, "Successfully deleted!")
    return redirect("posts:list")

urls.py

from django.conf.urls import url
from django.contrib import admin
from . import views

# from .views import (
#     post_list,
#     post_create,
#     post_detail,
#     post_update,
#     post_delete,
#     )

# video: https://www.youtube.com/watch?annotation_id=annotation_3160187747&feature=iv&index=14&list=PLEsfXFp6DpzQFqfCur9CJ4QnKQTVXUsRy&src_vid=nw3R2TXlkwY&v=1KuyH8JVn6A 
# shows a different solution here for version 1.10

urlpatterns = [
    #url(r'^$', views.post_home),
    # url(r'^$', views.post_list, name='list'),
    # url(r'^create/', views.post_create), #name='create'
    # url(r'^(?P<slug>[\w-]+)/', views.post_detail, name='detail'), 
    # url(r'^(?P<slug>[\w-]+)/edit/', views.post_update, name='update'),
    # url(r'^(?P<slug>[\w-]+)/delete/', views.post_delete),

    url(r'^$', views.post_list, name='list'),
    url(r'^create/$', views.post_create, name='create'),
    url(r'^(?P<slug>[\w-]+)/$', views.post_detail, name='detail'),
    url(r'^(?P<slug>[\w-]+)/edit/$', views.post_update, name='update'),
    url(r'^(?P<slug>[\w-]+)/delete/$', views.post_delete),

    # url(r'^$', posts.views.post_home),
    # url(r'^create/', home_create),
    # url(r'^list/', home_list),
    # url(r'^detail/', home_detail),
    # url(r'^update/', home_update),
    # url(r'^delete/', home_delete),

    # url(r'^posts/$', "<appname>.views.<function_name>"),
]

post_list.py

{% extends "base.html" %}

{% block head_title %}
{{ instance.title }} | {{ block.super }}
{% endblock head_title %}


{% block content %}

    <div class="row justify-content-md-center">
        <div class='col-md-8'>
            <h1>{{title}}</h1>
        </div>

        {% for obj in object_list %}

        <div class='col-md-8 pt-3'>
            <div class="card" style="min-width: 20rem;">
                {% if obj.image %}
                <img src="{{ obj.image.url }}" class="card-img-top">
                {% endif %}
                <div class="card-body">
                <h4 class="card-title">
                    <a href='{{ obj.get_absolute_url }}'>{{ obj.title }}</a>
                    <small>{{ obj.timestamp|timesince }} ago</small>
                </h4>
                <p class="card-text">{{ obj.content|linebreaks|truncatechars:120 }}</p>
                <p class="card-text">{{ obj.updated }}</p>
                <p class="card-text">{{ obj.id }}</p>
                <!-- <a href='{% url "posts:detail" id=obj.id %}'>{{ obj.title }}</a><br/>  -->
                <a href="{{ obj.get_absolute_url }}" class="btn btn-primary">View</a>
                </div>
            </div>
        </div>

        {% endfor %}

        <div class='col-md-8'>
            <div class="pagination">
                <span class="step-links">
                    {% if object_list.has_previous %}
                        <a href="?{{ page_request_var }}={{ object_list.previous_page_number }}">previous</a>
                    {% endif %}

                    <span class="current">
                        Page {{ object_list.number }} of {{ object_list.paginator.num_pages }}.
                    </span>

                    {% if object_list.has_next %}
                        <a href="?{{ page_request_var }}={{ object_list.next_page_number }}">next</a>
                    {% endif %}
                </span>
            </div>
        </div>

    </div>

{% endblock content %}

【问题讨论】:

  • 拜托,你能缩小你的问题范围吗?
  • 我也很高兴。只是不知道从哪里开始。我的问题是,在将我的博客文章从 ID 更改为 Slug URL 后,我现在得到一个错误页面。我可以扩展任何具体的内容吗?
  • 请不要发布错误图片。复制并粘贴问题中的文本。
  • 您的第一个版本的get_absolute_url 带有命名空间是正确的。问题是您在其他地方仍有一些代码正在调用 reverse 或使用带有 id 而不是 slug 的 {% url %} 标记。
  • @Alasdair 这很有意义(对链接感到抱歉,因为它更干净)。这就是我一直在寻找的。有什么我可以在这里发布你想看的吗?

标签: python regex django


【解决方案1】:

错误来自这一行

<!-- <a href='{% url "posts:detail" id=obj.id %}'>{{ obj.title }}</a><br/>  -->

&lt;!-- 是一个 html 注释,所以 Django 在渲染模板时仍然会尝试反转 url。

您可以完全删除该行,将其更改为 Django 注释 {# ... #},或将其更改为使用 slug 而不是 id。

【讨论】:

  • 哦,我的……你是我的英雄。您如何建议编写“安全”的 cmets?或者我应该把它们放在某些区域之外?
  • 正如我所说,Django 模板语言允许单行 comments 和 {# comment goes here #}。
猜你喜欢
  • 2023-03-17
  • 2018-06-25
  • 1970-01-01
  • 2016-11-12
  • 1970-01-01
  • 2020-11-06
  • 2023-03-11
  • 2021-12-20
  • 1970-01-01
相关资源
最近更新 更多