基于Django開(kāi)發(fā)的SkyNet博客一——?jiǎng)?chuàng)建模型
基于Django開(kāi)發(fā)的SkyNet博客二——base Template
基于Django開(kāi)發(fā)的SkyNet博客三——登錄注冊(cè)界面
代碼傳送門(mén) 這是我這個(gè)項(xiàng)目的github代碼庫(kù),目前項(xiàng)目正在更新隔显,所以代碼不是很全掘而。
上一篇博客主要講了博客的登錄注冊(cè)界面色乾,這一節(jié)想先修改一下上一節(jié)的登錄修改該界面廊营,先來(lái)個(gè)圖吧:
這樣修改主要是因?yàn)榭吹胶芏嗑W(wǎng)站的登錄注冊(cè)都在一個(gè)html上僵控,那么我也就改了一下霜运。改動(dòng)也不多勾邦,主要是html和views.py中修改了一丟丟
{% extends 'blog/base.html' %}
{% block title %}
SkyNet登錄
{% endblock %}
{% block content %}
{% load static %}
<link rel="stylesheet" href="{% static 'blog/css/form.css' %}" type="text/css">
<script type="text/javascript" src="{% static 'blog/js/login.js' %}"></script>
<div class="ui middle aligned center aligned grid">
<div class="column">
<div class="ui stacked segment">
<div class="ui two item menu">
<a class="item {% if islogin %} active {% endif %}" href="{% url 'blog:login' %}">登錄</a>
<a class="item {% if not islogin %} active {% endif %}" href="{% url 'blog:register' %}">注冊(cè)</a>
</div>
{% if islogin %}
<div id="login-div">
<form class="ui login form segment" method="post">
<div class="field">
<div class="ui input">
<input type="text" placeholder="郵箱或昵稱" name="name">
</div>
</div>
<div class="field">
<div class="ui input">
<input type="password" placeholder="密碼" name="pwd">
</div>
</div>
<div class="ui fluid large teal submit button">登錄</div>
</form>
</div>
{% else %}
<div id="register-div">
<form class="ui register form segment" method="post">
<div class="field">
<div class="ui input">
<input type="text" placeholder="昵稱" name="name">
</div>
</div>
<div class="field">
<div class="ui input">
<input type="text" placeholder="郵箱" name="email">
</div>
</div>
<div class="field">
<div class="ui input">
<input type="password" placeholder="密碼" name="pwd">
</div>
</div>
<div class="field">
<div class="ui input">
<input type="password" placeholder="再次輸入密碼" name="pwd2">
</div>
</div>
<div class="ui fluid large teal submit button">提交</div>
</form>
</div>
{% endif %}
</div>
</div>
</div>
{% endblock %}
其實(shí)改動(dòng)的并不多道川,在上一篇的基礎(chǔ)上合并了兩個(gè)html午衰,添加了一個(gè)menu
<div class="ui two item menu">
<a class="item {% if islogin %} active {% endif %}" href="{% url 'blog:login' %}">登錄</a>
<a class="item {% if not islogin %} active {% endif %}" href="{% url 'blog:register' %}">注冊(cè)</a>
</div>
two item menu會(huì)將menu分為平分為兩個(gè)部分立宜,然后通過(guò)views.py傳過(guò)來(lái)的islogin,來(lái)判斷是否該item是否是active臊岸,同樣也可控制顯示登錄窗口還是注冊(cè)窗口橙数。
其他的地方改動(dòng)都很小,主要是views.py中l(wèi)ogin和register最后返回的時(shí)候返回一個(gè)islogin參數(shù)即可
@csrf_exempt
def login(request):
if request.method == 'POST':
//和上一篇博客中代碼一致
......
return render(request, 'blog/login.html',{"islogin":True})
登錄注冊(cè)界面就到這里了帅戒。
下面就開(kāi)始來(lái)創(chuàng)建博客編輯界面了灯帮。
同樣的先上個(gè)圖
在博客二中的banner上有個(gè)寫(xiě)文章的按鈕
//base.html
<div class="item">
<button id="create_blog" class="ui primary button">寫(xiě)文章</button>
</div>
在js中對(duì)該button的click時(shí)間進(jìn)行了監(jiān)聽(tīng)
//base.js
$("#create_blog").on("click", function () {
$.ajax({
type: "get",
url: "/blog/create_blog/",
success: function (data) {
jsonobj = JSON.parse(data);
if(jsonobj.error == 1) {
window.location.href = '/blog/login';
}else {
window.location.href = '/blog/edit/' + jsonobj.id;
}
}
});
});
這段代碼的主要意圖是點(diǎn)擊寫(xiě)文章按鈕后,通過(guò)后臺(tái)傳遞的error值來(lái)判斷用戶是否登錄逻住,重定向到登錄界面钟哥,若已登錄則重定向到編輯界面。
首先來(lái)看一下create_blog方法
//blog/urls.py
url(r'^create_blog', create_blog, name='create'),
def create_blog(request):
if request.user.is_authenticated:
blog = Blog.objects.create(user=request.user)
return HttpResponse(simplejson.dumps({'error': 0, 'id': blog.pk}, ensure_ascii=False))
else:
return HttpResponse(simplejson.dumps({'error': 1}, ensure_ascii=False))
在這里我將models.py中的blog模型改動(dòng)了一下鄙信,所有的值都有默認(rèn)值瞪醋,在創(chuàng)建的時(shí)候只需要傳遞user即可。下面看一下blog models
class Blog(models.Model):
POST_STATUS = (
('P', '已發(fā)布'),
('D', '已刪除'),
('E', '正在編輯'),
)
title = models.CharField('標(biāo)題',max_length=150,default="無(wú)標(biāo)題文章")
body = models.TextField('正文',blank=True,default="")
create_time = models.DateTimeField('創(chuàng)建時(shí)間',auto_now_add=True)
modify_time = models.DateTimeField('最后一次修改',auto_now=True)
status = models.CharField('文章?tīng)顟B(tài)',max_length=1, choices=POST_STATUS,default='E')
views = models.PositiveIntegerField('瀏覽量', default=0)
likes = models.PositiveIntegerField('喜歡', default=0)
praises = models.PositiveIntegerField('點(diǎn)贊', default=0)
category = models.ManyToManyField('Category',symmetrical=False,blank=True)
user = models.ForeignKey('User',verbose_name='作者')
當(dāng)頁(yè)面重定向到編輯界面后装诡,也就是上面第一章圖的效果银受。
//urls.py
url(r'^edit/(?P<blog_id>\d+)', EditBlogView.as_view(), name='edit'),
這里url的定義使用到了TemplateView,也就是封裝好的view請(qǐng)求鸦采,只是開(kāi)放一些接口宾巍,參數(shù)而已。先看一下吧渔伯。
class EditBlogView(DetailView):
model = Blog
template_name = 'blog/user/edit.html'
pk_url_kwarg = 'blog_id'
context_object_name = 'blog'
def get_context_data(self, **kwargs):
context = super(EditBlogView, self).get_context_data(**kwargs)
blogs = self.request.user.blog_set.all()
context['blogs'] = blogs
return context
- 繼承DetailView顶霞,展示文章詳情,一般用來(lái)查詢單個(gè)數(shù)據(jù)锣吼。
- model即指定的model选浑,將在該model中進(jìn)行數(shù)據(jù)查詢,template_name即指定查詢結(jié)束將數(shù)據(jù)展示的模板中玄叠,pk_url_kwarg指查詢的條件古徒,context_object_name指定查詢返回的結(jié)果。
- get_context_data一般用來(lái)傳遞額外的數(shù)據(jù)读恃,這里我將該用戶的所有文章傳遞給了EditBlogView隧膘,用來(lái)制作文章列表顯示。
來(lái)看一下界面結(jié)構(gòu)
{% extends 'blog/base.html' %}
{% block title %}
文章編輯
{% endblock %}
{% block header %}
{% endblock %}
{% block content %}
{% load static %}
<link rel="stylesheet" href="{% static 'blog/css/edit.css' %}" type="text/css">
<script type="text/javascript" src="{% static 'blog/js/edit.js' %}"></script>
<i id="blog-id" data-index="{{ blog.pk }}" hidden></i>
<div id="back-index">
<a href="{% url 'blog:uindex' request.user.pk %} " class="ui primary button">返回主頁(yè)</a>
</div>
{% include 'blog/util/bloglist.html' %}
<div class="ui center aligned grid">
<div class="column">
<div class="ui menu">
<a id="blog_list" class="item">文章列表</a>
<div class="right menu">
<a id="save_blog" class="ui item">保存</a>
<a class="ui item">發(fā)布</a>
</div>
</div>
<form class="ui large form">
<div class="ui stacked segment">
<div class="field">
<div class="ui input">
<input id="title" type="text" placeholder="標(biāo)題" name="title" value="{{ blog.title }}">
</div>
</div>
<div class="field">
</div>
<div class="field">
<div class="ui input">
<textarea id="body" name="body" rows="15">{{ blog.body }}</textarea>
</div>
</div>
</div>
</form>
</div>
</div>
{% endblock %}
在這里我將主界面分為兩欄寺惫,一個(gè)是菜單欄疹吃,剩下的是標(biāo)題和內(nèi)容欄,其中內(nèi)容列表使用的是{% include %}方式引入一個(gè)html西雀。include和extends用法相同萨驶,include引入的話,可以將頁(yè)面中的功能獨(dú)立出去艇肴,這樣能夠保證頁(yè)面的整體結(jié)構(gòu)篡撵。
先來(lái)看一下保存按鈕功能
$("#save_blog").on("click",function () {
var $save_msg = $("<a class='ui item'>正在保存</a>");
$(".right.menu").prepend($save_msg)
var id = $("#blog-id").attr("data-index");
var title = $("#title").val();
var body = $("#body").val();
$.ajax({
type:"get",
url:'../save_blog/'+id,
data:{
'title':title,
'body':body
},
success:function (data) {
$save_msg.text("已保存");
$save_msg.animate({
opacity:0,
},2000,function () {
$(".right.menu").remove($save_msg);
});
}
})
});
在這里我添加了一個(gè)正在保存的item判莉,然后想后臺(tái)請(qǐng)求保存數(shù)據(jù),最后保存成功則顯示已保存育谬,然后慢慢消失券盅,最后刪除item。
def save_blog(request, blog_id):
blog = Blog.objects.get(pk=blog_id)
blog.title = request.POST.get('title')
blog.body = request.POST.get('body')
print(blog.title,blog.body)
blog.save()
return HttpResponse()
由于這里不需要向前臺(tái)傳遞數(shù)據(jù)膛檀,直接返回HttpResponse即可锰镀。
最后再展示一下sidebar的代碼吧
//bloglist.html
{% load static %}
<link rel="stylesheet" type="text/css" href="{% static 'blog/css/util/bloglist.css' %}">
<div id="left-menu" class="ui sidebar vertical menu">
<div class="item">
<a>返回首頁(yè)</a>
</div>
{% for blog in blogs %}
<div id="menu-item" class="item">
<a data-index="{{ blog.index }}">{{ blog.title }}</a>
<i class="trash icon"></i>
</div>
{% endfor %}
</div>
//edit.js
$("#blog_list").click(function () {
$(".ui.sidebar")
.sidebar('setting', 'transition', 'overlay')
.sidebar('toggle');
});
編輯界面就先寫(xiě)到這里了。