上一篇我们还留了一个小问题没有解决,其实这个问题我是特意留到这一篇来讲的,请往下看 ⇩
现在我们的博客已经具备了基本的页面,但是如果我想发表一篇新的文章的话,还得到数据库里手动添加。
而且如果我们想修改一篇文章的话也很麻烦,这时候一个后台管理界面就很有用了。
一、需求分析
在添加后台管理界面之前,让我们想一想需要一些什么功能:
- 能够添加文章
- 能够修改文章
- 能够删除文章
还有一些功能,比如在线编辑、实时预览、markdown支持我们以后再添加。
现在我们已经把功能列出来了,接下来就是分析一下需要什么页面:
- 查看所有文章的页面,在这个页面里应该有修改和删除文章的选项,还要有添加新文章的选项
- 点击修改文章应该出现编辑页面
- 点击删除文章应该出现确认页面
- 点击添加文章应该出现文章编辑页面,这个和修改文章的页面应该是相同的
然后在修改、添加、删除文章后应该返回文章列表。
二、显示文章页面
确定下来页面我们就可以开始敲代码了,按照页面之间的逻辑关系,我们先完成显示文章列表的页面。
这个页面和我们的首页很相似,我们只需要添加几个按钮即可:
{% extends 'myblog/base.html' %}
{% block title %}Post List{% endblock %}
{% block main %}
{% for post in pagedata.post_list %}
-
{% endfor %}
{% endblock %}
再把链接和视图添加上去,运行一下看看效果:
三、添加文章功能
添加一个新建文章的按钮:
现在按钮的位置都添加好了,我们分别为每个按钮添加链接,首先是添加文章的按钮,这个链接是一个固定的值,我们可以直接写到页面中去(当然,等以后页面多了肯定不能这么写,不过现在只有几个页面,所以问题不大)。
然后再创建一个视图和模板,再添加链接:
修改 urls.py文件:
# myblog/urls.py
from django.urls import re_path
from . import views
urlpatterns = [
re_path(r'^index/{0,1}$', views.index),
re_path(r'^article/\d{4,4}/\d{1,2}/(?P.+)/{0,1}$', views.article),
re_path(r'^articles/list/{0,1}$', views.article_list),
re_path(r'^addArticle/{0,1}$', views.addArticle),
]
创建一个模板文件 add_article.html:
{% extends 'myblog/base.html' %}
{% block title %}Add Article{% endblock %}
{% block main %}
{% endblock %}
再添加一个视图函数 addArticle:
def addArticle(request):
if request.method == 'GET':
return render(request, 'myblog/add_article.html')
elif request.method == 'POST':
title = request.POST['title']
key = abs(hash(title))
tags = request.POST['tags']
content = request.POST['content']
date = datetime.datetime.now().strftime('%Y-%m-%d')
Post(key=key, title=title, tags=tags, content=content, date=date).save()
return HttpResponseRedirect('/myblog/articles/list/')
当请求方式为 get请求时,addArticle函数会返回 add_article页面:
当请求方式为 post时,也就是点击提交后,addArticle函数会接收页面提交的数据,并将其保存到数据库中,然后重定向到 article_list页面查看添加结果。
注意到在保存到数据库时多了一个 key参数。
这就是我们用来替换 title用来查找文章的值,key是由 title经过哈希运算得到的值,我们可以认为 key和 title是一一对应的。
这样文章链接就可以根据 key来生成。
要应用这个变化,我们还需要修改一些文件:
首先修改文章的链接:
re_path(r'^article/\d{4,4}/\d{1,2}/(?P\d+)/{0,1}$', views.article),
然后修改 Post类的 get_absolute_url方法:
def get_absolute_url(self):
return f'/myblog/article/{self.date.year}/{self.date.month}/{self.key}'
注意:
这里链接以 ” / “开头说明该链接是相对于网站根目录的链接,即最终的链接是:
http://127.0.0.1:8000/myblog/article/2018/8/1/45555555544
如果不以 ” /“开头则说明该链接是相对于当前页面的链接,假设当前页面是
http://127.0.0.1:8000/myblog/index
那么最终的链接是:
http://127.0.0.1:8000/myblog/myblog/article/2018/8/1/45555555544
可以看到,myblog重复了两次,由于当前页面的不确定性,所以我们在所有的页面里都使用带反斜杠的链接。
改了上面两处还不够,我们还需要改一下 article视图函数,其实就是将 title改为了 key:
def article(request, key):
post = Post.objects.filter(key=key).get()
return render(
request,
'myblog/article.html',
{'pagedata':
{'post': post}
}
)
接下来访问一下文章详情页面 :
这样我们就把添加文章的功能给做好了,接下来我们再来完成修改文章的功能。
四、修改文章功能
首先我们先添加一个链接:
re_path(r'^modifyArticle/{0,1}$', views.modifyArticle)
再修改 articles_list.html模板文件,为每篇文章添加对应的修改链接:
再给 Post类添加 get_modify_url方法:
def get_modify_url(self):
return f'/modifyArticle/{self.key}'
做完这些我们还需要添加一个 modify_article模板:
{% extends 'myblog/base.html' %}
{% block title %}Modify Article{% endblock %}
{% block main %}
{% endblock %}
这个模板和 add_article模板基本一致,我们只做了一些小的改动。
我们为每个 input标签添加了一个 value,value的值就是文章对应属性的值。
最后我们还需要添加一个视图函数 modifyArticle来处理请求:
def modifyArticle(request, key):
if request.method == 'GET':
post_list = Post.objects.filter(key=key)
if len(post_list) == 0:
return HttpResponse('文章不存在')
else:
return render(
request,
'myblog/modify_article.html',
{'pagedata':
{'post':post_list[0]}
}
)
elif request.method == 'POST':
title = request.POST['title']
key = request.POST['key']
tags = request.POST['tags']
content = request.POST['content']
date = datetime.datetime.now().strftime('%Y-%m-%d')
post = Post.objects.filter(key=key)[0]
post.title = title
post.tags = tags
post.content = content
post.date = date
post.save()
return HttpResponseRedirect('/myblog/articles/list/')
我们来测试一下:
现在只剩下删除功能没有做了,删除功能其实很简单,只需要添加一个确认页面,然后在数据库里执行删除操作即可,这些我就不再多写了。
最后看看整体效果:
不过我们得后台管理还有很多问题,比如:没有进行身份验证。
在下一篇我们会为博客添加身份认证机制