自定义模型类使得django-taggit支持中文标签

一、问题描述

django-taggit是一个很好的给文章打标签的应用,但是它的模型存储的标签默认是只支持ascii的slug,不支持中文。为了让其支持中文,我们不能直接使用Tag模型类,而是应该自定义模型类。当然,这个自定义并不是从零开始,而是继承它提供的基类。

二、代码实现

说明:下面的基于Django3 by Example里的博客项目,但是我没有把全部代码写全,只写了我实现的自定义taggit模型类支持中文的部分。对此项目感兴趣的朋友可以自行阅读书籍。

models.py

from taggit.managers import TaggableManager
from taggit.models import TagBase,GenericTaggedItemBase
from django.utils.text import slugify
from django.utils.translation import gettext, gettext_lazy as _


class MyTag(TagBase):
    # 这一步是关键,要设置allow_unicode=True,这样这个字段才能支持中文
    slug = models.SlugField(verbose_name=_("slug"), unique=True, max_length=100,allow_unicode=True)
    
    # 这个方法也是要覆盖的,它是用来计算slug的,也是添加allow_unicode=True参数
    def slugify(self, tag, i=None):
        slug = slugify(tag,allow_unicode=True)
        if i is not None:
            slug += "_%d" % i
        return slug
    class Meta:
        verbose_name = _("tag")
        verbose_name_plural = _("tags")
        app_label = "taggit"


class TaggedWhatever(GenericTaggedItemBase):

    # 把我们自定义的模型类传进来,它就能知道如何处理
    tag = models.ForeignKey(
        MyTag,
        on_delete=models.CASCADE,
        related_name="%(app_label)s_%(class)s_items",
    )


class Post(models.Model):
    '''这是我们自己的博客文章模型类'''
    # 它的字段全省略了
    # ......
    # 声明这个manager也是基于我们自定义的模型类
    tags = TaggableManager(through=TaggedWhatever)

注意:定义了模型类之后要记得迁移数据库

views.py

from .models import Post,MyTag

def post_list(request,tag_slug=None):
    posts = Post.published.all()
    tag = None
    if tag_slug:
        # 从MyTag对应的数据库表里查询tag
        tag = get_object_or_404(MyTag,slug=tag_slug)
        # 因为文章和标签是多对多的关系,所以这里要把tag放到列表里面
        # 这里的意思是查询那些文章标签里包含给定标签的文章
        posts = object_list.filter(tags__in=[tag])


    return render(request,
                  'blog/post/list.html',
                  {'posts':posts,
                   'tag':tag})

urls.py(这是blog这个app自己的urls,不是总的UrlConf)

from django.urls import path

from . import views

app_name = 'blog'

urlpatterns = [
    # 下面的两个路由对应同一个视图
    # 如果没有标签,就是第一个路由
    # 提供了标签,就是第二个路由
    path('',views.post_list,name='post_list'),
    # 这里的参数类型不要写slug,否则又会忽视中文,写str就行了
    path('tag//',
         views.post_list,
         name='post_list_by_tag')
]

下面的屏幕截图是我选择了“娱乐”这个标签之后,两篇有“娱乐”标签的博客文章就被筛选出来了:

自定义模型类使得django-taggit支持中文标签_第1张图片

 

 

 

如果这篇博文帮到了你,就请给我点个吧(#^.^#)

有疑问也欢迎留言~博主可nice啦,在线秒回ヾ(◍°∇°◍)ノ゙

你可能感兴趣的:(Python学习)