这是我的第一个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 %}
答案 0 :(得分:1)
您为primary_key=True
模型中的title
字段设置了Post
,因此它没有自动生成的id
字段。来自documentation:
如果您要指定自定义主键,只需在其中一个字段中指定
primary_key=True
即可。如果Django发现您已明确设置Field.primary_key
,则不会添加自动id
列。
删除(并再次迁移)以添加id
列,或使用slug
作为post_share
视图的参数。
话虽如此,使用title
作为主键是一个坏主意,因为您可能需要在创建后更改博客帖子的标题。使用自动生成的数字id
字段(推荐),或者至少使用slug
作为主键。