我目前正在写一个网络博客,学习django。我需要一个视图来显示一个博客帖子,我的第一个尝试是为它创建一个URL,如下所示:
myblog.com/blog/view/1
这使用blog-id来标识指定的博客帖子。
现在,如果你看一下很多博客/网站,你会看到他们在网址中使用博客帖子的标题,这是因为这对搜索引擎更友好,因此可以更容易找到。这可能是这样的。
myblog.com/blog/view/a-python-backup-script
我如何在django中实现这个?
奖金问题: 许多网站还包括帖子的月份和年份。我想这也与SEO有关,但这究竟有用吗?
答案 0 :(得分:26)
在您的Blog模型中添加一个slug字段。
from django.template.defaultfilters import slugify
Class Blog(models.Model):
title = models.CharField(max_length=40)
slug = models.SlugField(_('slug'), max_length=60, blank=True)
#Then override models save method:
def save(self, *args, **kwargs):
if not self.id:
#Only set the slug when the object is created.
self.slug = slugify(self.title) #Or whatever you want the slug to use
super(Blog, self).save(*args, **kwargs)
在你的urls.py
中(r'^blog/view/(?P<slug>[-\w]+)/$', 'app.views.blog_view'),
在views.py
中def blog_view(request, slug):
blog = Blog.objects.get(slug=slug)
#Then do whatever you want
编辑:我在save方法中添加了一个检查,因为您希望在创建对象时创建slug。它不应该每次都被保存。
答案 1 :(得分:8)
确保您的模型实际上有一个slug字段:
class BlogPost(models.Model):
slug = models.SlugField(unique=True)
并且您有一个观点:
from django.shortcuts import get_object_or_404
def blog_detail(request, slug):
...
post = get_object_or_404(BlogPost, slug=slug)
...
render(request, "blog/blog_post.detail.html", { 'blog_post' : post })
然后在你的urls.py中,你可以指定一个slug:
url(r'^(?P<slug>[-w]+)/$', 'blog.views.blog_detail', {}, name="blog_detail"),
第一个参数是一个正则表达式,匹配时会运行视图blog_detail
视图并将匹配的slug
组从正则表达式传递给thew视图(它将依次呈现并返回模板)
关于你的最后一点:我发现在SEO方面也可能是积极的,在网址中设置日期可以让我更容易看到博客文章是否一目了然。此外,在Django中,使用这种方法和date-based generic views非常容易,这将减少您需要编写的样板视图代码的数量。这将是一个例子:
url(r'(?P<year>d{4})/(?P<month>[a-z]{3})/(?P<day>w{1,2})/(?P<slug>[-w]+)/$',
'django.views.generic.date_based.object_detail',
{ template_name = "blog/detail.html", ... },
name="blog_detail"),
答案 2 :(得分:2)
或者,如果您使用的是基于类的视图,那么您可以做的最基本的事情是:
from django.views.generic import DetailView
from models import Blog
class BlogView(DetailView):
model = Blog
template_name = "blog/blog_detail.html"
然后,网址看起来像这样:
from views import BlogView
url(r'^(?P<slug>[-w]+)/$', BlogView._as_view(), name="blog_detail"),
请注意,Django的通用DetailView需要pk或slug。因此,在这种情况下使用slug与使用pk没有什么不同。
答案 3 :(得分:2)
这种类似的方法向后兼容我们提供数字ID的网址。
在models.py中添加 slug字段和保存定义:
from django.template.defaultfilters import slugify
slug = models.SlugField(default='no-slug', max_length=60, blank=True)
def save(self, *args, **kwargs):
#save a slug if there is no slug or when it's 'no-slug' (the default slug)
if not self.slug or self.slug == 'no-slug':
self.slug = slugify(self.name)
super(Project, self).save(*args, **kwargs)
在urls.py中添加第二个网址格式:
#original:
url(r'^(?P<id>\d+)/$', 'project.views.view', name='view_url'),
#new pattern added under original:
url(r'^(?P<id>\d+)-(?P<slug>[-\w\d]+)/$', 'project.views.view', name='view_url'),
在views.py 让slug通过:
def view(request, mid=None, slug=None):
然后您需要做的就是使用此网址模式是编辑models.py:
def get_absolute_url(self):
return reverse('view_url', args=[self.id, self.slug])
答案 4 :(得分:0)
django-autoslug可以很好地用于此目的,并且有很多有用的选项。