在这篇博客中,咱们开始为咱们的博客开发Blogs App和Users App相关的管理功能,以便每一个用户都能管理本身的博客以及评论。目前,Users App的管理功能相对简单,主要功能为查看用户资料以及切换到博客管理页面,以下所示:javascript
在点击了博客管理后,页面将跳转到管理页面,在此可进行对博客的各类管理:css
咱们的博客管理操做支持对博客的编辑、删除,对草稿的编辑、删除和对评论的删除操做,以及尚未开发的类别管理功能。html
首先来添加用户管理功能。咱们须要开发一个新页面userIndex来做为用户管理的主页,在该页上会显示出该用户全部的博客列表,以及提供查看用户资料和博客管理的入口。为此,咱们须要添加在Users App的目录中添加userTemplate.html做为用户管理的模板,代码以下:前端
<!-- userTemplate.html --> <!DOCTYPE html> <html lang="zh"> <head> <meta charset="UTF-8"> <script type="text/javascript" src="/static/ckeditor/ckeditor-init.js" data-ckeditor-basepath="/static/ckeditor/ckeditor/" id="ckeditor-init-script"></script> <script type="text/javascript" src="/static/ckeditor/ckeditor/ckeditor.js"></script> <script type="text/javascript" src="/static/js/jquery-3.2.1.min.js"></script> <title>Cap_Liu的博客</title> </head> <style type="text/css"> <!-- CSS部分略 --> </style> <body> <h1>Cap_Liu的博客</h1> <div class="introduce"> {{ test }} </div> <div class="nav"> {% if username == currentUser.username and currentUser.username != "anony" %} <span><a href="{% url 'index' %}">首页</a></span> <span><a href="{% url 'users:userinfo' username %}">用户资料</a></span> <span><a href="{% url 'blogs:blogmanage' %}">博客管理</a></span> {% else %} <span><a href="{% url 'index' %}">首页</a> <span><a href="{% url 'users:userinfo' username %}">用户资料</a></span> {% endif %} </div> <div class="content"> {% block content %} {% endblock %} </div> </body> </html>在这里,要根据用户登陆的用户名来判断是否要显示出博客管理的入口。若查看的用户资料与当前登陆用户不符,则没法看到博客管理的入口。
而后,咱们创建userindex.html做为用户管理的首页,即显示出该用户全部的博客:java
<!-- userindex.html --> {% extends "userTemplate.html" %} {% block content %} <div id="content" class="list"> {% if blogList %} <ul> {% for blog in blogList %} <div class="articlelist"> <a href="{% url 'blogs:content' blog.id %}">{{ blog.title }}</a>-<a href="{% url 'users:userIndex' blog.auther.username %}">{{ blog.auther }}</a> <div class="articlelistinfo"> <span title="阅读次数">阅读 {{ blog.readcount }}</span> <span title="建立时间">{{ blog.createdate|date:"Y-m-d H:i:s" }}</span> </div> </div> {% endfor %} </ul> {% else %} <p>No blogs</p> {% endif %} </div> {% endblock %}
# users/views.py # ... def userIndex(request,username): try: user = Users.objects.get(username=username) currentUser = Users.objects.get(username=request.session['username']) blogList = Blog.objects.filter(auther=username).filter(draft=False) content = {'username':username, 'currentUser':currentUser, 'blogList':blogList } except Exception as e: content = {'username':e} return render(request,'users/userindex.html',content) # ...以及,因为如今咱们能够容许其余用户访问用户资料,所以咱们要对这个系列 第二篇中开发的userInfo函数进行修改,使之能根据不一样的用户名显示不一样用户的信息:
# users/views.py # ... def userinfo(request,username): try: user = Users.objects.get(username=username) currentUser = Users.objects.get(username=request.session['username']) birthday = user.birthday email = user.email registertime = user.registertime content = {'username':username, 'registertime':registertime, 'birthday':birthday, 'email':email, 'currentUser':currentUser } except Exception as e: pass return render(request,'users/userinfo.html',content) # ...同时,咱们也要对userInfo的url作对应的修改,以及添加userindex的url:
# users/urls.py # ... urlpatterns = [ # ... url(r'^userindex/(?P<username>.*)$',views.userIndex,name='userIndex'), url(r'^userinfo/(?P<username>.*)$',views.userinfo,name='userinfo') ]
所以,如今咱们来看看博客管理功能的实现。当前的博客管理功能包括5个页面articleList.html, blogmanage.html, commentmanage.html, draftmanage.html和failedoperation.html,分别对应文章列表、博客管理、评论管理、草稿箱和拒绝访问功能。为了保持页面风格的统一,以上页面都会继承blogManageTemplate.html模板,以下所示:python
<!-- blogManageTemplate.html--> <!DOCTYPE html> <html lang="zh"> <head> <meta charset="UTF-8"> <script type="text/javascript" src="/static/ckeditor/ckeditor-init.js" data-ckeditor-basepath="/static/ckeditor/ckeditor/" id="ckeditor-init-script"></script> <script type="text/javascript" src="/static/ckeditor/ckeditor/ckeditor.js"></script> <script type="text/javascript" src="/static/js/jquery-3.2.1.min.js"></script> <title>Cap_Liu的博客</title> </head> <style type="text/css"> <!--CSS部分略,与其余模板相同--> </style> <body> <h1>Cap_Liu的博客</h1> <div class="introduce"> {{ test }} </div> <div class="nav"> <span><a href="{% url 'index' %}">首页</a></span> <span><a href="{% url 'blogs:articlelist' %}">文章列表</a></span> <span><a href="{% url 'blogs:blogmanage' %}">博客管理</a></span> <span><a href="{% url 'blogs:commentmanage' %}">评论管理</a></span> <span>类别管理</span> <span><a href="{% url 'blogs:draftmanage' %}">草稿箱</a></span> </div> <div class="content"> {% block content %} {% endblock %} </div> <div class="content"> {% block comment %} {% endblock %} </div> </body> </html>
<!-- blogmanage.html --> {% extends "blogManageTemplate.html" %} {% block content %} <div id="content" class="list"> <table> <tr> <td>标题</td> <td> </td> <td>阅读数</td> <td> </td> <td>评论数</td> <td> </td> <td>操做</td> </tr> {% if blogList %} {% for blog in blogList %} <tr> <td><a href="{% url 'blogs:content' blog.id %}">{{ blog.title }}</a> ({{ blog.createdate|date:"Y-m-d H:i:s" }})</td> <td> </td> <td>{{ blog.readcount }}</td> <td> </td> <td>{{ blog.commentcount }}</td> <td> </td> <td><span><a href="{% url 'blogs:editBlog' blog.id %}">编辑</a></span>|<span><a href="javascript:void(0);" onClick="deleteConfirm('{{ blog.title }}','{{ blog.id }}')">删除</a></span> </tr> {% endfor %} {% else %} <p>No blogs</p> {% endif %} </table> </div> <script> function deleteConfirm(title,id) { var blogId = id; var url_mask = "{% url 'blogs:deleteBlog' 'tmpId' %}".replace('tmpId',blogId); if(confirm("确认删除" + title + "吗?")) { location.href = url_mask; } } </script> {% endblock %}在该页面中,会显示出博客的标题、阅读数和评论数,以及提供了编辑和删除的入口连接。这里值得注意的是,对于删除操做,咱们须要使用javascript提供一个confirm对话框,防止用户的误操做。而在javascript中,{% url %}标记的参数不能直接设为javascript的变量,所以咱们须要设置一个tmpId的占位符,在获得完整的url形式后再用replace函数把tmpId替换成真正的blogId,从而实现删除操做;而对于编辑操做,咱们须要将欲编辑的文章的标题、类别和内容填入到addBlog页面中的各个表单中,所以须要修改在 第七篇博客中的addBlog.html页面,使得表单的数据能够用后端数据直接填写:
<!-- addBlog.html --> <!--在javascript部分添加如下代码--> <script> $(document).ready(function(){ $("#id_title").val('{{ title }}'); $("#id_category").val('{{ category }}'); $("#id_content").val('{{ content|safe }}'); }); </script>下面来看一下blogmanage、editblog和deleteblog的view函数:
# blogs/views.py # ... def blogmanage(request): if request.session['username'] == 'anony': return render(request, 'blogs/failedoperation.html') else: blogList = Blog.objects.filter(auther=request.session['username']) return render(request, 'blogs/blogmanage.html', {'blogList': blogList}) def deleteblog(request,blogId): blog = Blog.objects.get(id=blogId) if blog.auther.username == request.session['username']: blog.delete() blogList = Blog.objects.filter(auther=request.session['username']) else: return render(request, 'blogs/failedoperation.html') return HttpResponseRedirect(reverse('blogs:blogmanage')) def editblog(request,blogId): tmpBlog = Blog.objects.get(id=blogId) request.session['currentblogId'] = blogId form = BlogForm() blogContent = {} if tmpBlog.auther.username == request.session['username']: blogContent = { 'title':tmpBlog.title, 'category':tmpBlog.category, 'content':tmpBlog.content, 'form':form } else: return render(request, 'blogs/failedoperation.html') return render(request, 'blogs/addblog.html', blogContent) # ...
<!-- failedoperation.html --> {% extends "blogManageTemplate.html" %} {% block content %} <div id="content" class="list"> <h2>没有权限进行此操做</h2> </div> {% endblock %}
在后端检查用户的目的在于,即便前端没法看到编辑或删除的入口,也能够经过拼凑url的方式达到非法编辑或删除的目的。而对于blogManage页面,咱们只需检查是否为匿名用户便可,由于该页面不会涉及任何具体操做,只是为编辑和删除操做提供入口。jquery
对于editblog,咱们能够复用addblog.html做为编辑的页面,并为其传入博客的标题、种类以及内容,以便经过javascript填入表单;同时,咱们还需将currentblogId的值设为当前编辑的blogId,表示咱们正在编辑该篇博客。后端
commentmanage.html用于显示该用户下全部博客的全部评论,包括评论内容、评论做者以及发表时间,博主能够对每条评论实施删除操做。页面代码以下:session
<!-- commentmanage.html --> {% extends "blogManageTemplate.html" %} {% block content %} <div id="content" class="list"> <table> <tr> <td>标题</td> <td> </td> <td>做者</td> <td> </td> <td>时间</td> <td> </td> <td>操做</td> </tr> {% if commentList %} {% for comment in commentList %} {% for realcomment in comment %} <tr> <td><a href="{% url 'blogs:content' blog.id %}">{{ realcomment.attachedblog.title }}</a> ({{ realcomment.attachedblog.createdate|date:"Y-m-d H:i:s" }})<br> {{ realcomment.content }} </td> <td> </td> <td>{{ realcomment.auther.username }}</td> <td> </td> <td>{{ realcomment.createtime }}</td> <td> </td> <td><span><a href="javascript:void(0);" onClick="deleteConfirm('{{ realcomment.id }}')">删除</a></span> </tr> {% endfor %} {% endfor %} {% else %} <p>No comments</p> {% endif %} </table> </div> <script> function deleteConfirm(id) { var commentid = id; var url_mask = "{% url 'blogs:deleteComment' 'tmpId' %}".replace('tmpId',commentid); if(confirm("确认删除该评论吗?")) { location.href = url_mask; } } </script> {% endblock %}
# blogs/views.py
# ... def commentmanage(request): blogList = Blog.objects.filter(auther=request.session['username']) commentList = [] for blog in blogList: commentList.append(Comment.objects.filter(attachedblog=blog)) return render(request,'blogs/commentmanage.html',{'commentList':commentList}) def deletecomment(request,commentId): comment = Comment.objects.get(id=commentId) attachedBlog = comment.attachedblog if attachedBlog.auther.username == request.session['username']: comment.delete() attachedBlog.commentcount -= 1 attachedBlog.save() else: return render(request, 'blogs/failedoperation.html') return HttpResponseRedirect(reverse('blogs:commentmanage'))
# ...在commentmanage函数里,咱们首先须要用username拿到该用户全部的blog,随后再根据每一个blog去获取其下全部的comment。此时,commentList的元素为QuerySet对象,所以在前端须要二重循环来显示全部的评论。
deletecomment相对简单,基本与deleteblog函数相同,要注意的是在删除评论后要将对应博客的commentcount-1。app
至于draftmanage.html,该页面与blogmanage.html相同,只不过在view函数中获取的是该用户全部draft=True的博客:
# blogs/views.py # ... def draftmanage(request): blogList = Blog.objects.filter(auther=request.session['username']).filter(draft=True) return render(request, 'blogs/draftmanage.html', {'blogList': blogList}) # ...而articleList.html页面与userindex.html相同,这里就再也不赘述。
最后是以上页面的url配置:
# blogs/urls.py urlpatterns = [ # ... # blog manage url(r'^articleList/$',views.articlelist,name='articlelist'), url(r'^blogmanage$',views.blogmanage,name='blogmanage'), url(r'^deleteblog/(?P<blogId>.*)$',views.deleteblog,name='deleteBlog'), url(r'^editblog/(?P<blogId>.*)$',views.editblog,name='editBlog'), url(r'^commentmanage$',views.commentmanage,name='commentmanage'), url(r'^deletecomment/(?P<commentId>.*)$',views.deletecomment,name='deleteComment'), url(r'^draftmanage$',views.draftmanage,name='draftmanage') ]这篇博文介绍了Users App和Blogs App的相关管理功能,篇幅比较长,主要是不想把Blogs App的管理部分拆成两部分来写,这样不利于程序的连贯性。至此,咱们的博客又添加了较为完备的博客管理功能,支持博主对博客进行编辑、删除以及管理评论等操做。在后续的博客中,将继续为你们带来学习Django的心得以及博客的新功能,但愿你们继续关注~