所謂的后臺(tái)管理闹啦,也就是對(duì)各個(gè)表格的增刪改查,顯示起來也是不盡相同辕坝。
分頁用之前寫好的類窍奋,直接套上去就能用了。
整個(gè)寫的雖然有些亂酱畅,不過還是十分不錯(cuò)的琳袄,邏輯很清晰,代碼分布有些亂
注意:整個(gè)django沒有寫 xss 攻擊防護(hù)圣贸,小心被攻擊啊
1.主頁
主頁上的菜單可篩選數(shù)據(jù)挚歧,通過 get 方式獲得 URL 中的 article id,進(jìn)行篩選文章吁峻。
2.登陸頁面
登陸和注冊(cè)都是由 form 來寫的滑负,點(diǎn)擊驗(yàn)證碼可以更換新的驗(yàn)證碼,同時(shí) session 中的驗(yàn)證碼一齊更改
注冊(cè)頁面
其中包含了對(duì)驗(yàn)證碼的驗(yàn)證用含,驗(yàn)證碼存在 request.session 中矮慕,便于提取和修改,登陸和注冊(cè)頁面的 input 和校驗(yàn)都在 form 中完成啄骇,form 可以校驗(yàn)數(shù)據(jù)和保存上一次輸入的值痴鳄,
我們整個(gè)頁面提交是由 form 表單來做的,一般來說缸夹,點(diǎn)擊 submit 提交就會(huì)發(fā)送數(shù)據(jù)到 action 中指定的路徑痪寻,效果就是刷新頁面螺句,丟失輸入的數(shù)據(jù),不過數(shù)據(jù)已經(jīng)發(fā)送到了后臺(tái)橡类,
利用 django 的 form 組件就不會(huì)丟失上次輸入的數(shù)據(jù)蛇尚。
3.后臺(tái)管理
搜索條件中對(duì)于保留上次輸入的值,是利用用戶請(qǐng)求的 URL 中匹配出來的 kwargs 獲取的顾画,取劫,
URL 設(shè)置為 /backend/article-2-2.html 的形式,對(duì)于每一列研侣,只需要修改其中一個(gè)數(shù)據(jù)谱邪,而另一個(gè)在 kwargs 中獲得,再在頁面中檢測(cè)是否選中庶诡。惦银。
也是利用篩選來做的,而各種效果就是 hover 灌砖, hide 的調(diào)用璧函,好看的button 和圖標(biāo)是用 bootstrap 和 font-awesome 來做的
4.文章管理
點(diǎn)擊文章的title就可以跳轉(zhuǎn)到詳細(xì)文章頁面,在主頁的title也可以跳轉(zhuǎn)
詳細(xì)頁面底下還有基显,評(píng)論和點(diǎn)贊蘸吓,富文本編輯框(KindEditor),
評(píng)論和點(diǎn)贊是關(guān)于用戶id在各個(gè)表中篩選出來的撩幽,(發(fā)表評(píng)論沒有寫)
富文本編輯框是直接引用插件的來完成的库继,點(diǎn)贊和踩就是發(fā)送一個(gè)ajax鏈接給后臺(tái),頁面不需要刷新窜醉,用 js 修改一下就行了(這個(gè)我沒做)宪萄,評(píng)論有評(píng)論的表格,篩選獲取就行榨惰,
做這個(gè)東西最重要的是表格之間的關(guān)系和篩選數(shù)據(jù)拜英,
需要建立了很多張表格,彼此互相關(guān)聯(lián)才行琅催。
5.頁面左邊也是可以點(diǎn)擊篩選的
篩選的方式基本都差不多居凶,不過在時(shí)間篩選上,要十分注意格式化時(shí)間字符串藤抡,用 strftime(這個(gè)是數(shù)據(jù)庫內(nèi)置的方法),
6.報(bào)障系統(tǒng)
(說成是系統(tǒng)我覺得有些過了侠碧,這個(gè)不過就是一個(gè)處理網(wǎng)頁罷了)
這個(gè)也就是用戶提交單子,給特定的人去取單缠黍,處理弄兜,其中的用戶提交單子之后的狀態(tài)轉(zhuǎn)變是很關(guān)鍵的一點(diǎn)
效果可以設(shè)置的更好看一些,不過這個(gè)費(fèi)事,我就沒怎么調(diào)替饿,直接在 bootstrap 和 font-awesome 上面找就行了
用戶創(chuàng)建報(bào)障單语泽,KindEditor插件
這個(gè)報(bào)障中十分重要的一點(diǎn)就是,普通用戶提交trouble盛垦,管理員解決trouble之間的關(guān)系湿弦,和各個(gè)管理員之間對(duì)報(bào)障單的爭(zhēng)奪,只有第一個(gè)點(diǎn)擊的人才能獲得單子
管理者取單
可以修改和不能修改之間的狀態(tài)的改變腾夯,改變之間又聯(lián)系在一起,這個(gè)部分寫的不是很完善蔬充,填坑要做很多改善啊
圖表
這個(gè)還是有必要記錄一下的蝶俱,用的插件是 hightchart,百度的echart也可以饥漫,用法都類似的榨呆,只需要傳入圖表所需要的數(shù)據(jù)類型就可以使得圖表出現(xiàn)數(shù)據(jù)了
程序:
boke.zip
鏈接:https://pan.baidu.com/s/1aYGgv2S7PdflQoLMiIXe0w 密碼:jpou
EdmureBlog.zip
鏈接:https://pan.baidu.com/s/1ThmBOgR4ofFLx4LDFYH_Ww 密碼:ovpo
(整個(gè)寫的有些亂,但是基本上還是不錯(cuò)的庸队,基本該有都有积蜻,修改一下就可以用了,注意:登陸和注冊(cè)有些小問題彻消,)
note
一竿拆、瀑布流
- 布局
- 文檔,窗口宾尚,滾動(dòng)
- 面向?qū)ο蟮姆庋b: this,that
二丙笋、報(bào)障系統(tǒng)
需求分析
- 報(bào)障
用戶:
提交報(bào)賬單
自己報(bào)障記錄
處理著:
查看所有人報(bào)障單
處理報(bào)賬單
- 知識(shí)庫(博客)
主頁:
展示最新文章
展示最熱文章
展示評(píng)論最多文章
分類查看
個(gè)人博客:
個(gè)人博客主頁
個(gè)人博客文章詳細(xì):贊,踩煌贴,評(píng)論
個(gè)人博客分類:標(biāo)簽御板、分類、時(shí)間
個(gè)人博客主題定制:后臺(tái)修改
后臺(tái)管理:
個(gè)人信息管理
個(gè)人標(biāo)簽
個(gè)人分類
個(gè)人文章
數(shù)據(jù)庫設(shè)計(jì):
用戶表: uid,username,pwd,email,img,
博客表: bid,surfix,theme,title,summary, FK(用戶表,unique)=OneToOne(用戶表)
互粉表: id 明星ID(用戶表) 粉絲ID(用戶表)
2 1
1 2
1 3
5 3
報(bào)障單:UUID title detail user(用戶表) processor(用戶表 null) status(待處理牛郑,處理中怠肋,已處理) 創(chuàng)建時(shí)間 處理事件
分類表:caption Fk(博客bid)
標(biāo)簽表:caption Fk(博客bid)
文章:id,title,summary,ctime,FK(個(gè)人分類表),主站分類(choices)
文章詳細(xì):detail OneToOne(文章)
文章標(biāo)簽關(guān)系: 文章ID 標(biāo)簽ID
贊踩文章關(guān)系: 文章ID 用戶ID 贊或踩(True,F(xiàn)alse) 聯(lián)合唯一索引:(文章ID 用戶ID )
評(píng)論表:id,content,FK(文章),FK(user),ctime,parent_comment_id
三淹朋、程序目錄結(jié)構(gòu)
project
- APP(repository) - 數(shù)據(jù)倉庫(操作數(shù)據(jù)Model)
- APP(backend) - 后臺(tái)管理
- APP(web) - 首頁笙各,個(gè)人博客
- utils - 工具包(公共模塊)
工作安排:
1. 需求分析
2. 數(shù)據(jù)庫設(shè)計(jì)思路
3. 實(shí)現(xiàn)數(shù)據(jù)庫設(shè)計(jì)(Admin添加數(shù)據(jù))
4. 主站:分類(主站)查看+分頁
- 標(biāo)題菜單:母版
- 登錄成功: session['username'] = 'root'
- 主頁html:
判斷是否有用戶:顯示用戶名
否則 : 登錄,注冊(cè)
<div class="pg-header">
{% if request.session.username %}
<a>{{ request.session.username }}</a>
{% else %}
<a>登錄</a><a>注冊(cè)</a>
{% endif %}
</div>
- 博文內(nèi)容布局:
div div -> float => 圖片下方空白
<a></a>asdflkjasdfkj => 文字環(huán)繞
- URL分類篩選:
url(r'^all/(?P<article_type_id>\d+).html$', home.index, name='index'),
url(r'^', home.index),
index根據(jù)kwargs判斷是否分類查詢瑞你?
a. 生成分類菜單
b. 考慮是否選中
c. 根據(jù)條件model.xxx.objects.filter(**kwargs)
- URL:
from django.urls import reverse
url(r'^all/(?<article_type_id>\d+).html$', home.index, name='index'),
在HTML中:{% url "index" article_type_id=1 %} => all/1.html
在views中:reverse('index',kwargs={"article_type_id":1}) =>all/1.html
url(r'^all/(\d+).html$', home.index, name='index'),
在HTML中:{% url "index" 1 %} =>all/1.html
在views中:reverse('index',args=(1,)) =>all/1.html
- 利用reverse+分頁組件完成:分類查看+分頁
5. 登錄酪惭,注冊(cè)
- 密碼:數(shù)字,字母者甲,特殊字符
- 密碼兩次輸入一致
提交:
v = MyForm(request.GET) # 6個(gè)字段
if v.is_valid():
pass
密碼示例:RegexField自定義密碼驗(yàn)證規(guī)則
password = forms.RegexField(
'^(?=.*[0-9])(?=.*[a-zA-Z])(?=.*[!@#$\%\^\&\*\(\)])[0-9a-zA-Z!@#$\%\^\&\*\(\)]{8,32}$',
min_length=12,
max_length=32,
error_messages={'required': '密碼不能為空.',
'invalid': '密碼必須包含數(shù)字春感,字母、特殊字符',
'min_length': "密碼長(zhǎng)度不能小于8個(gè)字符",
'max_length': "密碼長(zhǎng)度不能大于32個(gè)字符"}
)
class RegisterForm(BaseForm, django_forms.Form):
username = django_fields.CharField()
password = django_fields.CharField()
confirm_pwd = django_fields.CharField()
def clean(self):
v1 = self.cleaned_data['password']
v2 = self.cleaned_data['confirm_pwd']
if v1 == v2:
pass
else:
from django.core.exceptions import ValidationError
raise ValidationError('密碼輸入不一致')
def register(request):
v = RegisterForm(request.POST)
if v.is_valid():
pass
else:
v.errors['username']
v.errors['__all__']
v.errors[NON_FIELD_ERRORS]
{
__all__: [],
username: [],
password: []
confirm_pwd: []
}
return render(request, 'register.html', {'v':v})
register.html
{{v.errors.username.0}}
{{v.non_field_errors}}
補(bǔ)充: 驗(yàn)證碼
1.點(diǎn)擊更換驗(yàn)證碼
2.驗(yàn)證碼到底是否有必要是圖片?有
3.
服務(wù)端:
a. session中保存隨機(jī)驗(yàn)證碼鲫懒,如:87fs
b. 在頁面中顯示圖片
客戶端:
a. 顯示圖片
b. 在cookie中保存sessionid
驗(yàn)證碼圖片
驗(yàn)證碼字符串:87fs
sessionid='asdfasdfasdfasdfasdfasdf09'
{
"asdfasdfasdfasdfasdfasdf09": {'ck': 87fs}
"ffsdfsdfsdfsdfsqq243234234": {'ck': 98fd}
"ffsdfsdfsdfsdfsqq243234234": {'ck': 98fd}
"ffsdfsdfsdfsdfsqq243234234": {'ck': 98fd}
"ffsdfsdfsdfsdfsqq243234234": {'ck': 98fd}
"ffsdfsdfsdfsdfsqq243234234": {'ck': 98fd}
"ffsdfsdfsdfsdfsqq243234234": {'ck': 98fd}
"ffsdfsdfsdfsdfsqq243234234": {'ck': 98fd}
}
ffsdfsdfsdfsdfsqq243234234 : 9999
使用:
check_code.py
Monaco.ttf
<img src="/shizhengwen.html" onclick="changeImg(this);">
<script>
function changeImg(ths) {
ths.src = ths.src + "?"; # 這個(gè)可以做到刷新驗(yàn)證碼
}
</script>
def xiaoyun(request):
if request.method == "GET":
return render(request,'xiaoyun.html')
else:
input_code = request.POST.get('code')
check_cd = request.session['check_code']
print(input_code,check_cd)
return HttpResponse('...')
def shizhengwen(request):
"""生成驗(yàn)證碼圖片"""
# f = open('static/imgs/avatar/20130809170025.png','rb')
# data = f.read()
# f.close()
f = BytesIO()
img, code = create_validate_code()
request.session['check_code'] = code
img.save(f, 'PNG')
# request.session['CheckCode'] = code
return HttpResponse(f.getvalue())
補(bǔ)充: 一個(gè)月免登陸
request.session.set_expiry(60 * 60 * 24 * 30)
SESSION_COOKIE_AGE = 1209600
6. 個(gè)人博客
個(gè)人主頁:http://127.0.0.1:8000/wupeiqi.html
/(\w+).html -> func(site) # wupeiqi
# 個(gè)人信息
# 博客信息
- 數(shù)據(jù)庫字段+CSS文件名(warm嫩实,default)
文章最終:http://127.0.0.1:8000/wupeiqi/5.html
# 根據(jù)當(dāng)前 wupeiqi + 5
obj = article.objects.filter(nid=5,blog=blog).first()
冗余
# 富文本編輯框
CKEditor
UEEditor
TinyEditor
KindEditor
# 下載插件
# 基本使用KindEditor
個(gè)人篩選:
http://127.0.0.1:8000/wupeiqi/tag/2.html
http://127.0.0.1:8000/wupeiqi/category/3.html
http://127.0.0.1:8000/wupeiqi/date/2017-02.html
# 公告
# 分類
# 標(biāo)簽
# 時(shí)間
# 過濾
url(r'^(?P<site>\w+)/(?P<condition>((tag)|(date)|(category)))/(?P<val>\w+-*\w*).html$', home.filter),
# 當(dāng)前博客id、
# 數(shù)據(jù)庫內(nèi)置時(shí)間格式化函數(shù)
注意:個(gè)人主題定制
7. 后臺(tái)管理
用戶:
- 普通用戶(知識(shí)庫+提交報(bào)障單+個(gè)人信息)
- 管理員 (知識(shí)庫+提交報(bào)障單+個(gè)人信息+處理報(bào)障單)
- 超級(jí)管理員
- (知識(shí)庫+提交報(bào)障單+個(gè)人信息+處理報(bào)障單+報(bào)障統(tǒng)計(jì)信息)
- 權(quán)限管理
菜單:
- 知識(shí)庫管理
文章
還債:KindEditor,XSS攻擊
分類
標(biāo)簽
- 報(bào)障管理
個(gè)人保障
處理報(bào)障單
報(bào)障統(tǒng)計(jì)信息
畫圖
- 權(quán)限管理
菜單
權(quán)限
角色
========》后臺(tái)管理頁面《=======
依賴:
bootstrap
fontawsome
作業(yè):
知識(shí)庫管理:文章(Form驗(yàn)證)
8. 報(bào)障管理
后臺(tái)管理:
普通用戶:
報(bào)障列表窥岩,創(chuàng)建報(bào)障甲献,修改,【查看解決方案】【評(píng)分】
工程師:
報(bào)障列表【自己 or 未】
列表:
models.tb.objects.filter(Q(processor_id=1)|Q(status=1)).order_by('status')
查看報(bào)障單id=1:
接單:v = models.tb.objects.filter(id=1,status=1).update(processor_id=22,status=2)
處理:
填寫解決方案颂翼,提交status=3
===》 模板
老板:
查看所有信息
頁面:
圖
列表
# 每個(gè)處理者晃洒,
# 每個(gè)月處理了多少訂單
id 創(chuàng)建時(shí)間 內(nèi)容 處理者
1 2017-02-01 11:11 1
2 2017-03-01 11:11 11
3 2017-04-01 11:11 2
4 2017-05-01 11:11 1
5 2017-02-02 11:11 1
1. 思路
處理者列表 = select 處理著 from tb
for 處理者 in 處理者列表:
v = select * from tb where 處理者=處理者 group by 創(chuàng)建時(shí)間(2017-02)
2. 思路
# 每個(gè)月份全部門處理的訂單個(gè)數(shù)
select * from tb group by 創(chuàng)建時(shí)間(%Y-%m)
select
創(chuàng)建時(shí)間(%Y-%m),
(select count(id) from tb as T2 where 處理者=1 and T2.ctime = T1.ctime ),
(select count(id) from tb as T2 where 處理者=2 and T2.ctime = T1.ctime ),
from tb as T1 group by 創(chuàng)建時(shí)間(%Y-%m)
年月 id=1 id=2
2017-02 2
2017-03 0
2017-04 0
2017-05 1
sql 注入
user = input('請(qǐng)輸入用戶名') # xx or 1=1 -- (-- 是注釋)
pwd = input('請(qǐng)輸入密碼') # 123
sql = "select * from user where username=%s and password=%s" %(user,pwd,)
select * from user where username=xx or 1=1 -- and password=123
and 開始的都被注釋掉了
所以這句是永遠(yuǎn)成立的
cursor.execute(sql)
cursor.fetchall()
要注意一點(diǎn),就是在pycharm中對(duì)時(shí)間字段修改時(shí)只能以一段1528819200000 這種類型的時(shí)間戳形成存儲(chǔ)朦乏,想要修改成 2017-03-17 05:49:18.777722 格式的需要在 admin 或自己寫個(gè)頁面來存儲(chǔ)到數(shù)據(jù)庫球及。。