12

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

myblog.com/blog/view/1

这使用 blog-id 来识别指定的 blog-post。

现在,如果您查看许多博客/网站,您会发现它们在 url 中使用博客文章的标题,这是因为这对搜索引擎更友好,因此更容易找到。这可能看起来像这样。

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

我如何在 django 中实现这个?

额外问题:很多网站还包括帖子的月份和年份。我想这也与搜索引擎优化有关,但这到底有什么用呢?

4

5 回答 5

27

在您的 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。它不应该每次都保存。

于 2012-08-09T08:38:56.697 回答
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组从正则表达式传递给 w 视图(依次渲染并返回一个模板)

关于你的最后一点:我发现除了在 SEO 方面可能是积极的之外,在 url 中包含日期让我更容易一目了然地查看博客文章是否是新的。此外,在 Django 中,很容易将此方法与基于日期的通用视图一起使用,这将减少您需要编写的样板视图代码的数量。这将是一个例子:

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"),
于 2012-08-09T08:35:42.023 回答
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 没有什么不同。

于 2012-08-09T08:57:30.783 回答
2

这种类似的方法与我们使用数字 id 归档的 url 向后兼容。

在 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 中添加第二个url 模式:

#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):

然后,使用此 URL模式所需要做的就是编辑 models.py:

def get_absolute_url(self):
    return reverse('view_url', args=[self.id, self.slug])
于 2015-03-09T19:04:31.480 回答
0

django-autoslug 非常适合这个目的,并且有很多有用的选项。

于 2014-10-15T14:49:52.343 回答