Django+Nginx+uwsgi搭建自己的博客(八)
在这篇博客中,我们开始为我们的博客开发Blogs App和Users App相关的管理功能,以便每个用户都能管理自己的博客以及评论。目前,Users App的管理功能相对简单,主要功能为查看用户资料以及切换到博客管理页面,如下所示:
在点击了博客管理后,页面将跳转到管理页面,在此可进行对博客的各种管理:
我们的博客管理操作支持对博客的编辑、删除,对草稿的编辑、删除和对评论的删除操作,以及还没有开发的类别管理功能。
首先来添加用户管理功能。我们需要开发一个新页面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>
<!-- 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作为用户管理的首页,即显示出该用户所有的博客:
- <!-- 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 %}
<!-- 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 %}
userIndex的views函数如下:
- # 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)
- # ...
# 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)
- # ...
# 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')
- ]
# users/urls.py
# ...
urlpatterns = [
# ...
url(r'^userindex/(?P<username>.*)$',views.userIndex,name='userIndex'),
url(r'^userinfo/(?P<username>.*)$',views.userinfo,name='userinfo')
]
这样,我们的Users App的管理功能就开发完毕了。现在的Users App的管理功能比较简单,并没有提供修改资料的功能,更主要的是为博客管理功能提供一个入口。
因此,现在我们来看看博客管理功能的实现。当前的博客管理功能包括5个页面articleList.html, blogmanage.html, commentmanage.html, draftmanage.html和failedoperation.html,分别对应文章列表、博客管理、评论管理、草稿箱和拒绝访问功能。为了保持页面风格的统一,以上页面都会继承blogManageTemplate.html模板,如下所示:
- <!-- 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>
<!-- 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>
下面来看看5个分页面的实现。blogmanage.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 %}
<!-- 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>
<!-- 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)
- # ...
# 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:
- <!-- failedoperation.html -->
- {% extends "blogManageTemplate.html" %}
- {% block content %}
- <div id="content" class="list">
- <h2>没有权限进行此操作</h2>
- </div>
- {% endblock %}
<!-- failedoperation.html -->
{% extends "blogManageTemplate.html" %}
{% block content %}
<div id="content" class="list">
<h2>没有权限进行此操作</h2>
</div>
{% endblock %}
在后端检查用户的目的在于,即使前端无法看到编辑或删除的入口,也可以通过拼凑url的方式达到非法编辑或删除的目的。而对于blogManage页面,我们只需检查是否为匿名用户即可,因为该页面不会涉及任何具体操作,只是为编辑和删除操作提供入口。
对于editblog,我们可以复用addblog.html作为编辑的页面,并为其传入博客的标题、种类以及内容,以便通过javascript填入表单;同时,我们还需将currentblogId的值设为当前编辑的blogId,表示我们正在编辑该篇博客。
commentmanage.html用于显示该用户下所有博客的所有评论,包括评论内容、评论作者以及发表时间,博主可以对每条评论实施删除操作。页面代码如下:
- <!-- 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 %}
<!-- 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 %}
这里要注意的是我们要显示所有博客下的所有评论,因此我们使用了一个二重循环来查找。该页面的view函数如下:
- # blogs/views.py
# 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'))
# ...
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。
至于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})
- # ...
# 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')
- ]
# 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的心得以及博客的新功能,希望大家继续关注~
Django+Nginx+uwsgi搭建自己的博客(八)的更多相关文章
- Django+Nginx+uwsgi搭建自己的博客(五)
在上一篇博文中,向大家介绍了Users App和Index的前端部分的实现,以及前端与Django的通信部分.至此,我们的博客已经具备一个简单的雏形,可以将其部署在本地的服务器上了.目前较为流行的we ...
- Django+Nginx+uwsgi搭建自己的博客(四)
由于在上篇博文中仍然介绍了相当多的后端部分,导致原定于上篇介绍的前端部分“跳票”到了这篇.在此篇博文中,我将会介绍Users App和主页的前端部分,从而形成我们博客的一个雏形. 在前端部分,我们主要 ...
- Django+Nginx+uwsgi搭建自己的博客(一)
最近对写爬虫有些厌倦了,于是将方向转移到了Web开发上.其实在之前自己也看过一部分Flask的资料,但总觉得Flask的资料有些零散,而且需要的各种扩展也非常多.因此,我将研究方向转移到了另一个主流的 ...
- Django+Nginx+uwsgi搭建自己的博客(七)
上一篇博客中介绍了Blogs App的部分后端功能的实现,在这篇博客中,将继续为大家介绍Blogs App中前端功能的实现. 首先来看发布博客功能的前端页面.在blogs/templates/blog ...
- Django+Nginx+uwsgi搭建自己的博客(六)
这篇应该是2017年的最后一篇博客了,在这里首先祝大家元旦快乐! 从这篇博客开始,将会介绍Blogs App的功能实现,包括数据模型的建立.相关功能的视图函数的实现.前端页面的设计等,这意味着我们即将 ...
- Django+Nginx+uwsgi搭建自己的博客(二)
在上一篇博客中,为大家介绍了Django的一些基本概念以及建立了第一个App——Users,并且在数据库中建立了对应的表. 在这篇博客中,将为大家继续介绍数据库模型的定义和相关操作,以及Users A ...
- Django+Nginx+uwsgi搭建自己的博客(三)
(本来打算在这篇博文中介绍Users App的前端部分的,但写着写着就发现还需要铺垫很多东西才能把整个项目串的比较流畅些,因此这篇就继续介绍了后端的一些东西,前端的部分只好跳票到下一篇了-) 在上一篇 ...
- python3.x +django + nginx + uwsgi 搭建web服务
最近一直在用django开发自己的网站.在开发和线上环境的对接过程中遇到了许多的坑.所以想以一个老鸟的经历来写一下怎么 搭建web服务 一.python3.x .django .nginx .uwsg ...
- Linux - 搭建Web项目(Django + nginx + uwsgi)
工作中碰到需要使用Django + nginx + uwsgi 搭建项目环境 1. 搭建基本环境 需要有python环境,不多做说明 需要安装nginx,不多做说明 需要安装uwsgi: yum in ...
随机推荐
- 用CSS3画出一个立方体---转
css3实践—创建3D立方体 要想实现3D的效果,其实非常简单,只需指定一个元素为容器并设置transform-style:preserve-3d,那么它的后代元素便会有3D效果.不过有很多需要注意的 ...
- CSS选择器-常用搜集
标签选择器: div{ font-size=10px; color=red; background-color=yello; width=200px; height=200px; } <div& ...
- HDU 5213 分块 容斥
给出n个数,给出m个询问,询问 区间[l,r] [u,v],在两个区间内分别取一个数,两个的和为k的对数数量. $k<=2*N$,$n <= 30000$ 发现可以容斥简化一个询问.一个询 ...
- ZOJ 3782 G - Ternary Calculation 水
LINK:http://acm.zju.edu.cn/onlinejudge/showProblem.do?problemCode=3782 题意:给出3个数和两个符号(+-*/%) 思路:拿到题目还 ...
- Stat3—因子分析(Factor Analysis)
题注:主成分分析分析与因子分析也有不同,主成分分析仅仅是变量变换,而因子分析需要构造因子模型.主成分分析:原始变量的线性组合表示新的综合变量,即主成分:因子分析:潜在的假想变量和随机影响变量的线性组合 ...
- Spring Boot中使用Spring Security进行安全控制
我们在编写Web应用时,经常需要对页面做一些安全控制,比如:对于没有访问权限的用户需要转到登录表单页面.要实现访问控制的方法多种多样,可以通过Aop.拦截器实现,也可以通过框架实现(如:Apache ...
- python笔记之BytesIO
1. 什么是BytesIO BytesIO与StringIO类似,不同的是StringIO只能存放string,BytesIO是用来存放bytes的,它提供了在内存中读写字节的能力. 即在内存中读写字 ...
- javascript 中的 this 关键字详解
1.javascript 中 什么是 this? this 指的是当前行为执行的主体,或者是当前方法执行的主体 context:是当前行为或者方法执行的环境 实例: xx 去北京饭店吃东西:上下文是“ ...
- npm install ERR! code E400/E404
在安装webpack的过程中,出现了一个报错npm install ERR! code E400/E404 解决方法: 1.查看npm配置文件 是否有错误: 执行 npm config edit 查看 ...
- 阿里Java研发工程师实习面经,附面试技巧
作者:如何进阿里 链接:https://www.nowcoder.com/discuss/72899?type=0&order=0&pos=17&page=1 来源:牛客网 前 ...