本篇我们实现文章管理的最后一个核心功能:修改文章。
修改文章和创建文章实际上差不太多,需要注意两点:
- 修改文章需要传入ID,指定修改的文章
- 修改文章需要先读取文章内容,然后再更新
接下来我们就是按照MTV的模式来进行相关的代码实现了。
文章模型之前已经定义好了不需要做改变。
编写视图函数
在ariticle/views.py
中增加修改文章的视图函数article_update()
:
# 更新文章
def article_update(request, id):
"""
更新文章的视图函数
通过POST方法提交表单,更新titile、body字段
GET方法进入初始表单页面
id: 文章的 id
"""
# 获取需要修改的具体文章对象
article = Article.objects.get(id=id)
# 判断用户是否为 POST 提交表单数据
if request.method == "POST":
# 将提交的数据赋值到表单实例中
article_post_form = ArticleForm(data=request.POST)
# 判断提交的数据是否满足模型的要求
if article_post_form.is_valid():
# 保存新写入的 title、body 数据并保存
article.title = request.POST['title']
article.body = request.POST['body']
article.save()
# 完成后返回到修改后的文章中。需传入文章的 id 值
return redirect("article:article_detail", id=id)
# 如果数据不合法,返回错误信息
else:
return HttpResponse("表单内容有误,请重新填写。")
# 如果用户 GET 请求获取数据
else:
# 创建表单类实例
article_post_form = ArticleForm()
# 赋值上下文,将 article 文章对象也传递进去,以便提取旧的内容
context = { 'article': article, 'article_post_form': article_post_form }
# 将响应返回到模板中
return render(request, 'article/update.html', context)
在这个函数中我们做了如下:
- 在请求URL的时候,可以传入id参数
- 根据Request请求的方法不同,分别实现了查询和更新文章的功能
编写模板
更新文章模板和创建文章模板几乎一样,只是在标题和内容的input
输入框内我们提前传入了原有文章的对应内容。
新建templates/article/update.html
并写入:
{% extends "base.html" %} {% load static %}
{% 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="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 %}
修改URL
配置下路由:
urlpatterns = [
path('admin/', admin.site.urls),
path('hello/', views.hello),
re_path(r'^$', views.article_list),
path('list/', views.article_list, name='list'), # 展示文章
path('detail/<int:id>/', views.article_detail, name='detail'), # 文章详情
path('create/', views.article_create, name='create'), # 写文章
path('delete/<int:id>/', views.article_delete, name='delete'),# 删除文章
# 增加更新文章
path('update/<int:id>/', views.article_update, name='update'),
]
在文章详情页面tempaltes/article/detail.html
中添加修改文章的入口:
...
<div class="container">
<!-- <div class="row">-->
<!-- 标题及作者 -->
<h1 class="col-12 mt-4 mb-4">{
{ article.title }}</h1>
<div class="col-12 alert alert-primary">
<div class="col-12">
<a>作者:{
{ article.author }}</a>
 
<a>{
{ article.created|date:'Y-m-d H:i:s' }}</a>
 
<a href="#" data-bs-toggle="modal" data-bs-target="#myModal">删除文章</a>
<!-- 新增一个隐藏的表单 -->
<form
style="display:none;"
id="safe_delete"
action="{% url "delete" article.id %}"
method="POST"
>
{% csrf_token %}
<button type="submit">发送</button>
</form>
 
<a href="{% url "update" article.id %}">编辑文章</a>
</div>
</div>
这里我们再增加一个控制,只有作者才能修改和删除自己的文章。
先修改下我们的article 模型,将author字段修改为User模型的外键:
# 博客文章数据模型
class Article(models.Model):
# 文章id,主键
id = models.AutoField(primary_key=True)
# 文章作者。修改为User的外键,参数 on_delete 用于指定数据删除的方式
author = models.ForeignKey(User, on_delete=models.CASCADE)
# 文章标题,models.CharField 为字符串字段,用于保存较短的字符串,比如标题
title = models.CharField('标题',max_length=100)
# 文章正文,保存大量文本使用 TextField
body = models.TextField('文章正文')
# 文章创建时间,参数 default=timezone.now 指定其在创建数据时将默认写入当前的时间
created = models.DateTimeField(default=timezone.now)
# 文章更新时间,参数 auto_now=True 指定每次数据更新时自动写入当前时间
updated = models.DateTimeField(auto_now=True)
重新迁移下模型
python manage.py makemigrations article
然后在Detail模板中增加对用户的检验。
...
<!-- 写入 base.html 中定义的 content -->
{% block content %}
<!-- 文章详情 -->
<div class="container">
<!-- <div class="row">-->
<!-- 标题及作者 -->
<h1 class="col-12 mt-4 mb-4">{
{ article.title }}</h1>
<div class="col-12 alert alert-primary">
<div class="col-12">
<a>作者:{
{ article.author }}</a>
 
<a>{
{ article.created|date:'Y-m-d H:i:s' }}</a>
 
<!-- 只有作者可以修改文章 -->
{% if user == article.author %}
<a href="#" data-bs-toggle="modal" data-bs-target="#myModal">删除文章</a>
<!-- 新增一个隐藏的表单 -->
<form
style="display:none;"
id="safe_delete"
action="{% url "delete" article.id %}"
method="POST"
>
{% csrf_token %}
<button type="submit">发送</button>
</form>
 
<a href="{% url "update" article.id %}">编辑文章</a>
{% endif %}
</div>
</div>
运行服务器:
系统报错如下:
原因是我们之前的Article表中的Author存的是用户名,现在我们把它改成了User的外键,他们之间是通过ID来进行关联的。
所以我们需要手工将MySQL中的Article表中author_id的值修改为User id。
修改完之后重新启动服务器看下效果:
使用另外一个用户登录看看
结语
至此我们就实现了一篇文章的增、删、改、查四个核心功能。
接下来我们将开始学习用户管理的功能实现。