Django做一个简单的博客系统(14)----增加文章标签

前言

    添加一个文章标签功能.
    感谢大神的教程: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 }} 浏览&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>
</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">&laquo; 首页</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">尾页 &raquo;</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)
写在最后

    本文是个人的一些学习笔记,如有侵权,请及时联系我进行删除,谢谢大家.

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值