博客的文章类型通常不止一种:有时候你会写高深莫测的技术文章,有时候又纯粹只记录一下当天的心情。因此对文章的分类就显得相当的重要了,既方便博主对文章进行分类归档,也方便用户有针对性的阅读。而文章分类一个重要的途径就是设置栏目。栏目的模型实现文章栏目功能的方法有多种。你可以只是简单的在文章的Model中增加CharField()字段,以字符串的形式将栏目名称保存起来(实际上这种实现更像是“标签”,以后会讲到)。这样做的优点是比较简单;缺点也很明显,就是时间长了你可能会记混栏目的名字,并且也不方便对栏目的其他属性进行扩展。因此对文章栏目可以独立为一个Model,用外键与文章的Model关联起来。修改article/modles.py文件:article/models.py…class ArticleColumn(models.Model): """ 栏目的 Model """ # 栏目标题 title = models.CharField(max_length=100, blank=True) # 创建时间 created = models.DateTimeField(default=timezone.now) def str(self): return self.titleclass ArticlePost(models.Model): … # 文章栏目的 “一对多” 外键 column = models.ForeignKey( ArticleColumn, null=True, blank=True, on_delete=models.CASCADE, related_name=‘article’ ) …栏目的Model有两个字段,“名称”和“创建日期”。一篇文章只有一个栏目,而一个栏目可以对应多篇文章,因此建立“一对多”的关系。写好模型后记得用makemigrations和migrate指令迁移数据。列表中显示栏目添加测试数据模型写好之后就需要几条栏目的数据来进行测试。由于还没有写视图,因此需要善加利用Django自带的后台。首先把栏目模型注册到后台:article/admin.py…from .models import ArticleColumn# 注册文章栏目admin.site.register(ArticleColumn)然后就可以在后台中添加栏目的数据条目了:先随便添加了“HTML”、“Java”、“Django”这3条。在后台中随便打开一篇文章,“栏目”字段已经静静的在等你了:随机找几篇文章设置不同的栏目用于测试。重写文章列表之前我们用卡片类型的UI界面展示文章列表。卡片的好处是简洁大方,但是随着数据的增多,卡片小小的版面已经不堪重负了。因此这里重写list.html模板的列表循环:article/list.html…<!– 列表循环 –><div class=“row mt-2”> {% for article in articles %} <!– 文章内容 –> <div class=“col-12”> <!– 栏目 –> {% if article.column %} <button type=“button” class=“btn btn-sm mb-2 {% if article.column.title == ‘Django’ %} btn-success {% elif article.column.title == ‘Java’ %} btn-danger {% elif article.column.title == ‘HTML’ %} btn-warning {% endif %} " > {{ article.column }} </button> {% endif %} <!– 标题 –> <h4> <b> <a href=”{% url ‘article:article_detail’ article.id %}" style=“color: black;” > {{ article.title }} </a> </b> </h4> <!– 摘要 –> <div> <p style=“color: gray;"> {{ article.body|slice:‘100’ }}… </p> </div> <!– 注脚 –> <p> <!– 附加信息 –> <span style=“color: green;"> {{ article.total_views }} 浏览&nbsp;&nbsp;&nbsp; </span> <span style=“color: blue;"> {{ article.created|date:‘Y-m-d’ }} 发布&nbsp;&nbsp;&nbsp; </span> <span style=“color: darkred;"> {{ article.updated|date:‘Y-m-d’ }} 更新 </span> </p> <hr> </div> {% endfor %}</div>…最主要的改动就是新增了展现“栏目”的按钮。我们甚至还为不同的栏目设置了不同的按钮颜色。在附加信息中顺便还把之前没有用到的日期信息也添加上去了。来看看效果:感觉还不错!修改写文章功能展示已经没问题了,但是发表新文章时还不能选择栏目。修改写文章的模板,在表单中新增下面的内容:templates/article/create.html…<!– 提交文章的表单 –><form method=“post” action=”."> {% csrf_token %} <!– 文章标题 –> … <!– 文章栏目 –> <div class=“form-group”> <label for=“column”>栏目</label> <select class=“form-control” id=“column” name=“column” > <option value=“none”>请选择栏目..</option> {% for column in columns %} <option value=”{{ column.id }}">{{ column }}</option> {% endfor %} </select> </div> <!– 文章正文 –> … <!– 提交按钮 –> …</form><select>是表单的下拉框选择组件。在这个组件中循环列出所有的栏目数据,并且设置value属性,指定表单提交栏目的id值。刷新页面,效果像下面这样:跟之前一样,能够展示了,但是还没有处理表单的视图逻辑。修改已有的写文章视图article_create(),让其能够处理表单上传的栏目数据:article/views.py# 引入栏目Modelfrom .models import ArticleColumn…# 写文章的视图…def article_create(request): if request.method == “POST”: … if article_post_form.is_valid(): … # 新增的代码 if request.POST[‘column’] != ’none’: new_article.column = ArticleColumn.objects.get(id=request.POST[‘column’]) # 已有代码 new_article.save() … else: … # 新增及修改的代码 columns = ArticleColumn.objects.all() context = { ‘article_post_form’: article_post_form, ‘columns’: columns } …新增代码涉及get和post两部分:POST:主要考虑某些文章是可以没有栏目的。因此用if语句判断该文章是否有栏目,如果有,则根据表单提交的value值,关联对应的栏目。GET:增加栏目的上下文,以便模板使用。测试一下,写文章的栏目功能应该可以正常工作了。修改更新视图更新文章的视图同样也需要升级一下。还是先更改模板:templates/article/update.html…<!– 提交文章的表单 –><form method=“post” action=”."> {% csrf_token %} <!– 文章标题 –> … <!– 文章栏目 –> <div class=“form-group”> <label for=“column”>栏目</label> <select class=“form-control” id=“column” name=“column” > <option value=“none”>请选择栏目..</option> {% for column in columns %} <option value=”{{ column.id }}" {% if column.id == article.column.id %} selected {% endif %} > {{ column }} </option> {% endfor %} </select> </div> <!– 文章正文 –> … <!– 提交按钮 –> …</form>…与前面稍有不同的是,表单中判断了column.id与article.column.id是否相等,如果相等则将其设置为默认值。然后修改视图函数:article/views.py# 更新文章…def article_update(request, id): … # 判断用户是否为 POST 提交表单数据 if request.method == “POST”: … if article_post_form.is_valid(): … # 新增的代码 if request.POST[‘column’] != ’none’: article.column = ArticleColumn.objects.get(id=request.POST[‘column’]) else: article.column = None … else: … # 新增及修改的代码 columns = ArticleColumn.objects.all() context = { ‘article’: article, ‘article_post_form’: article_post_form, ‘columns’: columns, } …代码逻辑与前面很类似。修改文章的栏目功能,也就完成了。总结本章实现了简单的栏目功能,可以舒舒服服对文章进行分类了,强迫症福音啊。还有些可以完善的工作,比如:单击栏目按钮显示所有相同栏目的文章。这个功能与之前学过的最热文章排序以及搜索文章非常的类似。还记得filter()方法吗?栏目Model的增删改查。对个人博客来说,栏目数据的变动通常是很少的。如果你不想写增删改查,用后台修改数据是完全可以的。以上内容就不再赘述了。留给读者去尝试实现。有疑问请在杜赛的个人网站留言,我会尽快回复。或Email私信我:dusaiphoto@foxmail.com项目完整代码:Django_blog_tutorial