在开发web
系统中,关于内容url
链接,有时候我们常常希望可以自定义,而不是看起来没有任何含义的id
来表示,这时候Django
提供给我们的SlugField
就能排上用场了。
slug
实际的含义是标称, 单位的意思。在 django
中,slug
指有效 URL
的一部分,能使 URL
更加清晰易懂。比如有这样一篇文章,标题是”我是中国人”,它的 URL
地址是/posts/wo-shi-zhong-guo-ren
,后面这一部分便是 slug
。
Django内置slugify
为了便于自动生成slug
,Django
甚至帮我们内置了该扩展,但是使用过程中会发现,并不适合国人,它对于汉语的支持很不友好,生成不了中文对应的slug
。
1 2 3 4 5
| >>> from django.template.defaultfilters import slugify >>> slugify('hello world') 'hello-world' >>> slugify('我是中国人') ''
|
可以看到中文生成不了对应的slug
了。
django-uuslug
django-uuslug
是一个很方便的将中文转化成拼音 slug
的插件。通过使用 django-uuslug
,可以确保 slug
是唯一的,并且都是 unicode
编码的。
安装
1
| pip install django-uuslug
|
测试
1 2 3 4 5
| >>> from uuslug import slugify >>> slugify('hello world') 'hello-world' >>> slugify('我是中国人') 'wo-shi-zhong-guo-ren'
|
项目应用
定义模型
网上大部分的做法是一步写死,直接自动生成slug,且禁止编辑。我们自己项目中有时候想让slug显得更有意义,所以有时候需要自己编辑slug,不主动设定slug时候才自动生成slug。
网上做法
1 2 3 4 5 6 7 8 9 10 11 12 13
| from django.db import models
from uuslug import slugify from django.template.defaultfilters import slugify
class Post(models.Model): title = models.CharField(verbose_name="文章标题", max_length=50) slug = models.SlugField(editable=False)
def save(self, *args, **kwargs): self.slug = slugify(self.title) super(Post, self).save(*args, **kwargs)
|
代码优化
将slug设为可编辑可为空,保存时判断用户没有填写slug我们在生成slug,这样显得更人性化。
1 2 3 4 5 6 7 8 9 10 11 12 13 14
| from django.db import models
from uuslug import slugify from django.template.defaultfilters import slugify
class Post(models.Model): title = models.CharField(verbose_name="文章标题", max_length=50) slug = models.SlugField(verbose_name="别名", max_length=50, null=True, blank=True)
def save(self, *args, **kwargs): if not self.slug: self.slug = slugify(self.title) super(Post, self).save(*args, **kwargs)
|
定义视图
使用CBV
模式写了简单两个视图,一个列表页,一个详情页
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37
| import json
from django.shortcuts import HttpResponse from django.http import JsonResponse from django.views import View
from . import models
class PostView(View): """文章列表视图"""
def get(self, request): posts = models.Post.objects.all() data = [] for post in posts: data.append({ 'title': post.title, 'slug': post.slug }) return JsonResponse({"data": data}, json_dumps_params={"ensure_ascii": False})
class PostDetailView(View): """文章详情视图"""
def get(self, request, slug): post_obj = models.Post.objects.filter(slug=slug).get() data = { 'title': post_obj.title, 'slug': post_obj.slug } return JsonResponse({"data": data}, json_dumps_params={"ensure_ascii": False})
|
添加数据
我们在django-admin
中添加了两条测试数据,一条自己编辑slug
的文章,一条自动生成slug
的文章
![]()
设置路由
路由我们这里肯定也要相对应的设置两条,分别对应列表页和详情页。
1 2 3 4
| path('post/', views.PostView.as_view()),
path('post/<slug:slug>/', views.PostDetailView.as_view())
|
访问测试
启动该Django
程序。
访问列表页
![]()
访问详情页
![]()
![]()
至此,我们的slug
从定义到使用全部说完了,更多高阶用法去官方文档翻翻看吧。