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!