前言
添加一个文章栏目功能.
感谢大神的教程:Django搭建个人博客.
一.文章栏目
1.修改模型
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.title
class ArticlePost(models.Model):
...
# 文章栏目的 “一对多” 外键
column = models.ForeignKey(
ArticleColumn,
null=True,
blank=True,
on_delete=models.CASCADE,
related_name='article'
)
...
2.添加测试数据
先修改article/admin.py:
...
from .models import ArticleColumn
# 注册文章栏目
admin.site.register(ArticleColumn)
然后进入:http://127.0.0.1:8000/admin添加栏目数据.
3.重写文章列表
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 }}">
最新
</a>
</li>
<li class="breadcrumb-item">
<a href="{% url 'article:article_list' %}?order=total_views&search={{ search }}">
最热
</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 %}
<nav aria-label="breadcrumb">
<ol class="breadcrumb">
<li class="breadcrumb-item">
<a href="{% url 'article:article_list' %}">
最新
</a>
</li>
<li class="breadcrumb-item">
<a href="{% url 'article:article_list' %}?order=total_views">
最热
</a>
</li>
</ol>
</nav>
<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 }} 浏览
</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 }}" class="btn btn-success">« 首页</a>
<span>...</span>
<a href="?page={{ articles.previous_page_number }}&order={{ order }}&search={{ search }}"
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 }}"
class="btn btn-secondary">{{ articles.next_page_number }}</a>
<span>...</span>
<a href="?page={{ articles.paginator.num_pages }}&order={{ order }}&search={{ search }}"
class="btn btn-success">尾页 »</a>
{% endif %}
</span>
</div>
</div>
{% endblock content %}
4.修改写文章功能
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="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 %}
5.修改写文章视图
article/views.py:
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()
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)
6.修改更新模板
article/update.html:
{% extends "base.html" %} {% load staticfiles %}
{% block title %} 更新文章 {% endblock title %}
{% block content %}
<div class="container">
<div class="row">
<div class="col-12">
<br>
<form method="post" action=".">
{% csrf_token %}
<div class="form-group">
<label for="title">文章标题</label>
<!-- 在 value 属性中指定文本框的初始值为旧的内容,即 article 对象中的 title 字段 -->
<input type="text" class="form-control" id="title" name="title" value="{{ article.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 }}"
{% if column.id == article.column.id %}
selected
{% endif %}
>
{{ column }}
</option>
{% endfor %}
</select>
</div>
<div class="form-group">
<label for="body">文章正文</label>
<!-- 文本域不需要 value 属性,直接在标签体中嵌入数据即可 -->
<textarea type="text" class="form-control" id="body" name="body" rows="12">{{ article.body }}</textarea>
</div>
<button type="submit" class="btn btn-primary">完成</button>
</form>
</div>
</div>
</div>
{% endblock content %}
7.修改更新视图
article/views.py:
def article_update(request,id):
"""
更新文章的视图函数
通过
POST方法提交表单,更新title,body字段
GET方法进入初始表单页面
id:是文章的id
"""
# 获取需要修改的具体文章对象
article = ArticlePost.objects.get(id=id)
if request.user != article.author:
return HttpResponse('抱歉,你无权限修改这篇文章')
# 判断用户是否为POST提交表单数据
if request.method == "POST":
article_post_form = ArticlePostForm(data=request.POST)
# 判断提交的数据是否满足模型的需求
if article_post_form.is_valid():
article.title = request.POST.get('title')
article.body = request.POST.get('body')
if request.POST['column'] != 'none':
article.column = ArticleColumn.objects.get(id=request.POST['column'])
else:
article.column = None
article.save()
# 完成后返回到修改后的文章中,需要传入文章的id值
return redirect("article:article_detail",id=id)
else:
return HttpResponse('表单内容有误,请重新填写')
# 如果是get请求
else:
article_post_form = ArticlePostForm()
columns = ArticleColumn.objects.all()
context = {'article': article,
'article_post_form': article_post_form,
'columns':columns}
# 将响应返回到模板中
return render(request, 'article/update.html', context)
写在最后
本文是个人的一些学习笔记,如有侵权,请及时联系我进行删除,谢谢大家.