代码改变世界

137-使用django实现分类功能,基于django 3.0的最新特性

2020-09-08 17:17  lzhshn  阅读(746)  评论(0编辑  收藏  举报

学习python web编程直接使用了最新的版本,python 3.8和django 3.0,默认安装都是最新版本。

以下是我用django实现的分类功能。功能主体已经实现,但是在admin后台和模板中的编辑页面,分类显示英文的value而不是中文lable,但是在最终渲染之后显示时,都显示lable。

不知道有谁知道如何在admin和模板里,都显示中文的label???

 

【1】关于TextChoices

我们自己定义的分类Category基于TextChoices,写法为:value = label,可以有多个label,需要加上引号,并且用逗号分开。

class Category(models.TextChoices):
    UNKNOWN = '默认'
    CULTURE = '文化'
    SCIENCE = '科技'
    NATURAL = '自然'
    EMOTION = '情感'
    LIFE = '生活'
    WORK = '工作'

  

【2】将定义的分类使用到其他模型中

注意这条:

note_category = models.CharField(max_length=64, choices=Category.choices, default=Category.UNKNOWN)

使用choices进行关联,并且指定了默认值。之后,使用note.note_category即可获得其分类。

class MyNote(models.Model):
    user = models.ForeignKey(User, on_delete=models.CASCADE)
    author = models.CharField(max_length=64)
    title = models.CharField(max_length=64, default='a default title')
    note_category = models.CharField(max_length=64, choices=Category.choices, default=Category.UNKNOWN)
    content = RichTextField(config_name='awesome_ckeditor')
    pub_time = models.DateTimeField(auto_now_add=True)
    pub_date = models.DateField(auto_now_add=True)
    update_time = models.DateTimeField(auto_now=True)
    praise_count = models.BigIntegerField(default=0)
    collect_count = models.BigIntegerField(default=0)
    comment_num = models.BigIntegerField(default=0)
    hot_index = models.BigIntegerField(default=0)
    open_bool = models.BooleanField(default=True)
    personal_tags = TaggableManager()

    def __str__(self):
        return self.title[0:32]

  

【3】分类是一级菜单。我们设定点击分类后进入到分类页面,并且默认打开的是“默认”分类。

这里特别要注意,由于首页被很多其他页面作为母模板,如果你尝试在首页的{% url %}里使用一个变量作为值,则必须要在所有继承或者次级继承的模板里,都要在上下文里传入相关值,这种做法可以说是个死穴!

因此可以看到,这里有些链接直接带有一些常量值。当然:常量并不是随意写的,是一系列参数中的一个“可确认”的值。

        <div id="menu">
            <span class="menu_item"><a href="{% url 'notebook:start_page' %}">首页</a></span>
            <span class="menu_item"><a href="{% url 'notebook:category' '默认' %}">分类</a></span>
            <span class="menu_item"><a href="{% url 'notebook:my_notes' 1 %}">我的</a></span>
            <span class="menu_item"><a href="{% url 'notebook:add_note' %}">新增</a></span>
            <span class="menu_item"><a href="{% url 'notebook:all_clt' 1 %}">收藏</a></span>
            <span class="menu_item"><a href="{% url 'notebook:add_note' %}">消息</a></span>
        </div>

  

【4】处理分类页面的函数

函数接收一个分类值,比如从“分类”点进来,以及切换分类菜单的操作,都会传来一个分类值。

cg里面其实都是‘默认’、‘工作’这种字符串,也就是lable!

为什么用lable来传值,而不是value传值?请看:cg_open_note = MyNote.objects.filter(open_bool=True, note_category=cg).order_by('-pub_time')

这里note_category=cg,就是Category定义时的写法,前面提到过:value = label

这里通过两个过滤,将公开的,并且属于这个分类的文章,全部保存下来。

@login_required
def category(request, cg):
    cg_open_note = MyNote.objects.filter(open_bool=True, note_category=cg).order_by('-pub_time')
    context = {'cg_open_note': cg_open_note, 'Category': Category}
    return render(request, 'category.html', context)

  

【5】分类模板

这里对所继承的模板的两个block部分都进行了改写,一边显示当前分类的所有文章(暂未做分页处理),另一边列举所有分类。

在django中,如果用for——in——取不到内容时,可以使用一个便捷方法{% empty %},显示替代内容。

列举所有分类的方法时直接对所定义的Category直接进行for——in——取值。

Category是一个特殊的模型类,它没有实例,也没有关联关系,也不能在admin里注册,它定义后,这个类本身即可直接使用。

<body>

{% block content %}
<div class="left">
    {% for note in cg_open_note %}

        <h3><a href="{% url 'notebook:op_one_note' note.pk %}">{{note.title}}</a></h3>
        <p>分类:{{note.note_category}} 作者:{{note.author}} 发表:{{note.pub_time}} 更新:{{note.update_time}}</p>
        {% autoescape off %}
        <p>{{note.content|truncatechars:1024}}</p>
        {% endautoescape %}
        {# <p>权限:{{note.open_bool}}</p> #}
        <p>{{note.personal_tags.all}}</p>
        {% empty %}
        <p>此分类下,暂无文章。不如你来发表第一篇吧!</p><a href="{% url 'notebook:add_note' %}">发表新文章</a>

    {% endfor %}


</div>
{% endblock content %}

{%block side %}
<div class="right">
    <h4>所有分类</h4>
    {% for cg in Category %}
    <p><a href="{% url 'notebook:category' cg %}">{{cg}}</a></p>
    {% endfor %}

</div>
{% endblock side %}

</body>

  

以上就是django进行分类功能的实现。使用了最新的django 3.0特性:TextChoices!