前言
添加一个文章标签功能.
感谢大神的教程:Django搭建个人博客.
一.文章标签
1.准备
首先要安装Django-taggit::
pip install django-taggit
安装成功后,修改项目配置,添加库:
settings.py:
INSTALLED_APPS = [
...
'taggit',
]
2.修改文章模型
article/models.py:
# Django-taggit
from taggit.managers import TaggableManager
...
class ArticlePost(models.Model):
...
# 文章标签
tags = TaggableManager(blank=True)
...
3.修改文章表单类
article/forms.py:
class ArticlePostForm(forms.ModelForm):
class Meta:
...
fields = ('title', 'body', 'tags')
4.修改发表文章视图
article/views.py:
@login_required(login_url='/userprofile/login/')
def article_create(request):
# 判断用户是否提交数据
if request.method == "POST":
# 将提交的数据赋值到表单实例中
article_post_form = ArticlePostForm(data=request.POST)
# 判断提交的数据是否满足模型的需求
if article_post_form.is_valid():
# 保存数据,但暂时不提交到数据库中
new_article = article_post_form.save(commit=False)
# 指定数据库中,id=1的用户为作者
# 如果你进行过删除数据表的操作,可能会找不到id=1的用户
# 此时请重新创建用户,并传入此用户id
new_article.author = User.objects.get(id=request.user.id)
if request.POST['column'] != 'none':
new_article.column = ArticleColumn.objects.get(id=request.POST['column'])
# 将新文章保存到数据库中
new_article.save()
article_post_form.save_m2m()
return redirect('article:article_list')
else:
return HttpResponse('表单内容有误,请重新填写')
# 如果用户请求获取数据
else:
# 创建表单实例
article_post_form = ArticlePostForm()
columns = ArticleColumn.objects.all()
context = {'article_post_form':article_post_form,'columns':columns}
return render(request,'article/create.html',context)
5.修改模板,添加表单项
templates/article/create.html:
{% extends "base.html" %}
{% load staticfiles %}
{% block title %}}写文章{% endblock %}
{% block content %}
<!-- 写文章表单 -->
<div class="container">
<div class="row">
<div class="col-12">
<br>
<!-- 提交文章的表单 -->
<form method="post" action=".">
<!-- Django中需要POST数据的地方都必须有csrf_token -->
{% csrf_token %}
<!-- 文章标题 -->
<div class="form-group">
<!-- 标签 -->
<label for="title">文章标题</label>
<!-- 文本框 -->
<input type="text" class="form-control" id="title" name="title">
</div>
<!-- 文章栏目 -->
<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>
<!-- 文章标签 -->
<div class="form-group">
<label for="tags">标签</label>
<input type="text"
class="form-control col-3"
id="tags"
name="tags"
>
</div>
<!-- 文章正文 -->
<div class="form-group">
<label for="body">文章正文</label>
<!-- 文本区域 -->
<textarea type="text" class="form-control" id="body" name="body" rows="12"></textarea>
</div>
<!-- 提交按钮 -->
<button type="submit" class="btn btn-primary">完成</button>
</form>
</div>
</div>
</div>
{% endblock %}
6.修改文章列表模板
templates/article/list.html:
<!-- extends表明此页面继承自 base.html 文件 -->
{% extends "base.html" %}
{% load staticfiles %}
<!-- 写入 base.html 中定义的 title -->
{% block title %}
首页
{% endblock title %}
<!-- 写入 base.html 中定义的 content -->
{% block content %}
<!-- 定义放置文章标题的div容器 -->
<div class="container">
<nav aria-label="breadcrumb">
<ol class="breadcrumb">
<li class="breadcrumb-item">
<a href="{% url 'article:article_list' %}?search={{ search }}&column={{ column }}&tag={{ tag }}">
最新
</a>
</li>
<li class="breadcrumb-item">
<a href="{% url 'article:article_list' %}?order=total_views&search={{ search }}&column={{ column }}&tag={{ tag }}">
最热
</a>
</li>
</ol>
</nav>
<!-- 新增,搜索栏 -->
<div class="row">
<div class="col-auto mr-auto">
<form class="form-inline" >
<label class="sr-only">content</label>
<input type="text"
class="form-control mb-2 mr-sm-2"
name="search"
placeholder="搜索文章..."
required
>
</form>
</div>
</div>
<!-- 新增,搜索提示语 -->
{% if search %}
{% if articles %}
<h4><span style="color: red">"{{ search }}"</span>的搜索结果如下:</h4>
<hr>
{% else %}
<h4>暂无<span style="color: red">"{{ search }}"</span>有关的文章。</h4>
<hr>
{% endif %}
{% endif %}
<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 %}
<!-- 标签 -->
<span>
{% for tag in article.tags.all %}
<a href="{% url 'article:article_list' %}?tag={{ tag }}"
class="badge badge-secondary"
>
{{ tag }}
</a>
{% endfor %}
</span>
<!-- 标题 -->
<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 }} 浏览
</span>
<span style="color: blue;">
{{ article.created|date:'Y-m-d' }} 发布
</span>
<span style="color: darkred;">
{{ article.updated|date:'Y-m-d' }} 更新
</span>
</p>
<hr>
</div>
{% endfor %}
</div>
</div>
<!-- 页码导航 -->
<div class="pagination row">
<div class="m-auto">
<span class="step-links">
<!-- 如果不是第一页,则显示上翻按钮 -->
{% if articles.has_previous %}
<a href="?page=1&order={{ order }}&search={{ search }}&column={{ column }}&tag={{ tag }}" class="btn btn-success">« 首页</a>
<span>...</span>
<a href="?page={{ articles.previous_page_number }}&order={{ order }}&search={{ search }}&column={{ column }}&tag={{ tag }}"
class="btn btn-secondary">
{{ articles.previous_page_number }}
</a>
{% endif %}
<!-- 当前页面 -->
<span class="current btn btn-danger btn-lg">
{{ articles.number }}
</span>
<!-- 如果不是最末页,则显示下翻按钮 -->
{% if articles.has_next %}
<a href="?page={{ articles.next_page_number }}&order={{ order }}&search={{ search }}&column={{ column }}&tag={{ tag }}"
class="btn btn-secondary">{{ articles.next_page_number }}</a>
<span>...</span>
<a href="?page={{ articles.paginator.num_pages }}&order={{ order }}&search={{ search }}&column={{ column }}&tag={{ tag }}"
class="btn btn-success">尾页 »</a>
{% endif %}
</span>
</div>
</div>
{% endblock content %}
7.修改列表视图
article/views.py:
def article_list(request):
# 从 url 中提取查询参数
search = request.GET.get('search')
order = request.GET.get('order')
column = request.GET.get('column')
tag = request.GET.get('tag')
# 初始化查询集
article_list = ArticlePost.objects.all()
# 搜索查询集
if search:
article_list = article_list.filter(
Q(title__icontains=search) |
Q(body__icontains=search)
)
else:
search = ''
# 栏目查询集
if column is not None and column.isdigit():
article_list = article_list.filter(column=column)
# 标签查询集
if tag and tag != 'None':
article_list = article_list.filter(tags__name__in=[tag])
# 查询集排序
if order == 'total_views':
article_list = article_list.order_by('-total_views')
paginator = Paginator(article_list, 3)
page = request.GET.get('page')
articles = paginator.get_page(page)
# 需要传递给模板(templates)的对象
context = {
'articles': articles,
'order': order,
'search': search,
'column': column,
'tag': tag,
}
return render(request, 'article/list.html', context)
写在最后
本文是个人的一些学习笔记,如有侵权,请及时联系我进行删除,谢谢大家.