Django搭建博客(五):为博客添加后台管理功能

上一篇我们还留了一个小问题没有解决,其实这个问题我是特意留到这一篇来讲的,请往下看 ⇩

现在我们的博客已经具备了基本的页面,但是如果我想发表一篇新的文章的话,还得到数据库里手动添加。

而且如果我们想修改一篇文章的话也很麻烦,这时候一个后台管理界面就很有用了。

一、需求分析

在添加后台管理界面之前,让我们想一想需要一些什么功能:

  • 能够添加文章
  • 能够修改文章
  • 能够删除文章

还有一些功能,比如在线编辑、实时预览、markdown支持我们以后再添加。

现在我们已经把功能列出来了,接下来就是分析一下需要什么页面:

  • 查看所有文章的页面,在这个页面里应该有修改和删除文章的选项,还要有添加新文章的选项
  • 点击修改文章应该出现编辑页面
  • 点击删除文章应该出现确认页面
  • 点击添加文章应该出现文章编辑页面,这个和修改文章的页面应该是相同的

然后在修改、添加、删除文章后应该返回文章列表。

二、显示文章页面

确定下来页面我们就可以开始敲代码了,按照页面之间的逻辑关系,我们先完成显示文章列表的页面。

这个页面和我们的首页很相似,我们只需要添加几个按钮即可:

{% extends 'myblog/base.html' %}

{% block title %}Post List{% endblock %}

{% block main %}

<ul class="list-unstyled">
{% for post in pagedata.post_list %}
<li>
    <div class="row">
        <div class="col-lg-10">
            <h1><a href="{{post.get_absolute_url}}">{{post.title}}</a></h1>
            <span class="d-block">{{post.tags}}</span>
            <span class="d-block">{{post.get_format_date}}</span>
            <p>{{post.get_brief_content}}</p>
        </div>
        <div class="col-lg-2">
            <div class="row">
                <div class="col"><a href="#">修改</a></div>
            </div>
            <div class="row">
                <div class="col"><a href="#">删除</a></div>
            </div>
        </div>
    </div>
</li>
{% endfor %}
 </ul>

{% endblock %}

再把链接和视图添加上去,运行一下看看效果:

8516750-f8f95f7dcf7c9b75.png

三、添加文章功能

添加一个新建文章的按钮:

8516750-1baa7b9afd525921.png

现在按钮的位置都添加好了,我们分别为每个按钮添加链接,首先是添加文章的按钮,这个链接是一个固定的值,我们可以直接写到页面中去(当然,等以后页面多了肯定不能这么写,不过现在只有几个页面,所以问题不大)。

<div class="add-article">
    <a class="text-success" href="/myblog/addArticle">添加文章</a>
</div>

然后再创建一个视图和模板,再添加链接:

修改 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<title>.+)/{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 %}

<div class="row">
    <div class="col">
        <form action="/myblog/addArticle" method="post">
            {% csrf_token %}
            <div class="row my-3">
                <div class="col">
                    <label for="title">标题</label>
                    <input type="text" name="title" id="title">
                </div>
            </div>
            <div class="row my-3">
                <div class="col">
                    <label for="tags">标签</label>
                    <input type="text" name="tags" id="tags">
                </div>
            </div>
            <div class="row my-3">
                <div class="col">
                    <label for="content">正文</label>
                    <textarea class="d-block" type="text" name="content" id="content"></textarea>
                </div>
            </div>
            <div class="row my-3">
                <div class="col">
                    <button type="submit">提交</button>
                </div>
            </div>
        </form>
    </div>
</div>

{% 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页面:

8516750-22c10b577a6dafeb.png

当请求方式为 post时,也就是点击提交后,addArticle函数会接收页面提交的数据,并将其保存到数据库中,然后重定向到 article_list页面查看添加结果。

注意到在保存到数据库时多了一个 key参数。

这就是我们用来替换 title用来查找文章的值,key是由 title经过哈希运算得到的值,我们可以认为 key和 title是一一对应的。

这样文章链接就可以根据 key来生成。

要应用这个变化,我们还需要修改一些文件:

首先修改文章的链接:

re_path(r'^article/\d{4,4}/\d{1,2}/(?P<key>\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}
        }
    )

接下来访问一下文章详情页面 :


8516750-efa275943c3c30f5.png

这样我们就把添加文章的功能给做好了,接下来我们再来完成修改文章的功能。

四、修改文章功能

首先我们先添加一个链接:

re_path(r'^modifyArticle/{0,1}$', views.modifyArticle)

再修改 articles_list.html模板文件,为每篇文章添加对应的修改链接:

<div class="row">
    <div class="col text-info">
        <a href="{{post.get_modify_url}}">修改</a>
    </div>
</div>

再给 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 %}

<div class="row">
    <div class="col">
        <form action="{{pagedata.post.get_modify_url}}" method="post">
            {% csrf_token %}
            <div class="row my-3">
                <div class="col">
                    <label for="title">标题</label>
                    <input type="text" name="title" id="title" value="{{pagedata.post.title}}">
                </div>
            </div>
            <div class="row my-3">
                <div class="col">
                    <label for="tags">标签</label>
                    <input type="text" name="tags" id="tags" value="{{pagedata.post.tags}}">
                </div>
            </div>
            <div class="row my-3">
                <div class="col">
                    <label for="content">正文</label>
                    <textarea class="d-block" type="text" name="content" id="content">{{pagedata.post.content}}</textarea>
                </div>
            </div>
            <input type="hidden" name="key" value="{{pagedata.post.key}}">
            <div class="row my-3">
                <div class="col">
                    <button type="submit">提交</button>
                </div>
            </div>
        </form>
    </div>
</div>

{% 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/')

我们来测试一下:

8516750-1cfa29c32d3fa330.gif

现在只剩下删除功能没有做了,删除功能其实很简单,只需要添加一个确认页面,然后在数据库里执行删除操作即可,这些我就不再多写了。

最后看看整体效果:


8516750-b1b17981a4de6bdc.gif

不过我们得后台管理还有很多问题,比如:没有进行身份验证。
在下一篇我们会为博客添加身份认证机制

猜你喜欢

转载自blog.csdn.net/weixin_33843409/article/details/87430539