在這篇博客中,咱們開始爲咱們的博客開發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的心得以及博客的新功能,但願你們繼續關注~