NoReverseMatch at / blog / 2017/04/27 / test_asset-purchase_2 /

时间:2017-04-27 07:36:29

标签: python django

这是我的第一个Django项目,我正在关注这本书" Django by Example"。我创建了一个HTML页面来列出我创建的所有帖子,这个页面效果很好,但如果我点击任何一个链接,就会出现以下错误:

错误消息:

NoReverseMatch at /blog/2017/04/27/test_asset-purchase_2/
Reverse for 'post_share' with arguments '('',)' not found. 1 pattern(s) tried: ['blog/(?P<post_id>\\d+)/share/$']


Request Method:
GET 

Request URL:
http://127.0.0.1:8000/blog/2017/04/27/test_asset-purchase_2/ 

Django Version:
1.11 

Exception Type:
NoReverseMatch 

Exception Value:
Reverse for 'post_share' with arguments '('',)' not found. 1 pattern(s) tried: ['blog/(?P<post_id>\\d+)/share/$']


Exception Location:
E:\workspace\pycharm\djangobyexample\mysite\env\lib\site-packages\django\urls\resolvers.py in _reverse_with_prefix, line 497 

Python Executable:
E:\workspace\pycharm\djangobyexample\mysite\env\Scripts\python.exe 

Python Version:
3.5.2 

Python Path:
['E:\\workspace\\pycharm\\djangobyexample\\mysite',
 'E:\\workspace\\pycharm\\djangobyexample\\mysite\\env\\Scripts\\python35.zip',
 'E:\\workspace\\pycharm\\djangobyexample\\mysite\\env\\DLLs',
 'E:\\workspace\\pycharm\\djangobyexample\\mysite\\env\\lib',
 'E:\\workspace\\pycharm\\djangobyexample\\mysite\\env\\Scripts',
 'c:\\users\\richard\\appdata\\local\\programs\\python\\python35\\Lib',
 'c:\\users\\richard\\appdata\\local\\programs\\python\\python35\\DLLs',
 'E:\\workspace\\pycharm\\djangobyexample\\mysite\\env',
 'E:\\workspace\\pycharm\\djangobyexample\\mysite\\env\\lib\\site-packages']

Models.py

from django.db import models
from django.utils import timezone
from django.contrib.auth.models import User
from django.core.urlresolvers import reverse


class PublishedManager(models.Manager):
    def get_query(self):
        return super(PublishedManager, self).get_query().filter(status='published')


class Post(models.Model):
    STATUS_CHOICES = {
        ('draft', 'Draft'),
        ('published', 'Published'),
    }
    title = models.CharField(max_length=250, primary_key=True)
    slug = models.SlugField(max_length=250, unique_for_date='publish')
    author = models.ForeignKey(User, related_name='blog_post')
    body = models.TextField()
    publish = models.DateTimeField(default=timezone.now)
    created = models.DateTimeField(auto_now_add=True)
    updated = models.DateTimeField(auto_now=True)
    status = models.CharField(max_length=10, choices=STATUS_CHOICES, default='draft')

    class Meta:
        # Telling django to sort results by the publish field in descending order by default when we query the database
        ordering = ('-publish',)

    def __str__(self):
        return self.title

    objects = models.Manager()
    published = PublishedManager()

    def get_absolute_url(self):
        # print(self.publish.year, self.publish.strftime('%m'), self.publish.strftime('%d'), self.slug)
        print(self.publish.year,
              self.publish.strftime('%m'),
              self.publish.strftime('%d'),
              self.slug)
        return reverse('blog:post_detail', args=[self.publish.year,
                                                 self.publish.strftime('%m'),
                                                 self.publish.strftime('%d'),
                                                 self.slug])

Views.py

from django.shortcuts import render, get_object_or_404
from .models import Post
from django.core.paginator import Paginator, EmptyPage, PageNotAnInteger
from django.views.generic import ListView
from .forms import EmailPostForm
from django.core.mail import send_mail


# Create your views here.

class PostListView(ListView):
    queryset = Post.published.all()
    context_object_name = 'posts'
    paginate_by = 3
    template_name = 'blog/post/list.html'


def post_list(request):

    object_list = Post.published.all()
    paginator = Paginator(object_list, 3)
    page = request.GET.get('page')
    try:
        posts = paginator.page(page)
    except PageNotAnInteger:
        posts = paginator.page(1)
    except EmptyPage:
        posts = paginator.page(paginator.num_pages)

    return render(request, 'blog/post/list.html', {'page': page, 'posts': posts})


def post_detail(request, year, month, day, post):
    post = get_object_or_404(Post, slug=post,
                             status='published',
                             publish__year=year,
                             publish__month=month,
                             publish__day=day)

    return render(request, 'blog/post/detail.html', {'post': post})


def post_share(request, post_id):
    # Receive post vvy id
    post = get_object_or_404(Post, id=post_id, status='published')
    sent = False

    if request.method == 'POST':
        # Form was submitted
        form = EmailPostForm(request.POST)
        if form.is_valid():
            # Form fields passed validation
            cd = form.cleaned_data
            post_url = request.build_absolute_uri(post.get_absolute_url())
            subject = '{} ({}) recommends you reading "{}"'.format(cd['name'], cd['email'], post.title)
            message = 'Read "{}" at {}\n\n{}\'s comments: {}'.format(post.title, post_url, cd['name'], cd['comments'])
            send_mail(subject, message, 'admin@myblog.com',)
            sent = True

    else:
        form = EmailPostForm()
    return render(request, 'blog/post/share.html', {'post': post, 'form': form, 'sent': sent})

博客/ urls.py

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

urlpatterns = [
    # post views
    url(r'^$', views.post_list, name='post_list'),
    url(r'^(?P<year>\d{4})/(?P<month>\d{2})/(?P<day>\d{2})/(?P<post>[-\w]+)/$',
        views.post_detail,
        name='post_detail'),
    url(r'^(?P<post_id>\d+)/share/$', views.post_share, name='post_share'),
]

detail.html

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

{% block title %}{{ post.title }}{% endblock %}

{% block content %}
    <h1>{{ post.title }}</h1>
    <p class="date">
        Published {{ post.publish }} by {{ post.author }}
    </p>
    {{ post.body|linebreaks }}
    <p>
        <a href="{% url 'blog:post_share' post.id %}">
            Share this post
        </a>
    </p>
{% endblock %}

1 个答案:

答案 0 :(得分:1)

您为primary_key=True模型中的title字段设置了Post,因此它没有自动生成的id字段。来自documentation

  

如果您要指定自定义主键,只需在其中一个字段中指定primary_key=True即可。如果Django发现您已明确设置Field.primary_key,则不会添加自动id列。

删除(并再次迁移)以添加id列,或使用slug作为post_share视图的参数。

话虽如此,使用title作为主键是一个坏主意,因为您可能需要在创建后更改博客帖子的标题。使用自动生成的数字id字段(推荐),或者至少使用slug作为主键。