django中的漂亮和seo友好的网址

时间:2012-08-09 08:25:35

标签: django url seo

我目前正在写一个网络博客,学习django。我需要一个视图来显示一个博客帖子,我的第一个尝试是为它创建一个URL,如下所示:

myblog.com/blog/view/1

这使用blog-id来标识指定的博客帖子。

现在,如果你看一下很多博客/网站,你会看到他们在网址中使用博客帖子的标题,这是因为这对搜索引擎更友好,因此可以更容易找到。这可能是这样的。

myblog.com/blog/view/a-python-backup-script

我如何在django中实现这个?

奖金问题: 许多网站还包括帖子的月份和年份。我想这也与SEO有关,但这究竟有用吗?

5 个答案:

答案 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可以很好地用于此目的,并且有很多有用的选项。