BBS 項目開發邏輯梳理
第一步:先進行數據庫設計
數據庫設計規則是:
1.先創建基表:用戶表、站點表、文章表、標簽表、分類表、文章2標簽第三張關系表、點贊點踩表、評論表
2.書寫表中的基本含有的字段
3.添加外鍵(一對一,一對多,多對多)
4.第三張關系表
注意事項:創建外鍵關系的時候,to='表名',不要忘記引號,null=true,並不是所有的外鍵都加的
第二步settings配置
一定要進行settings的相關配置:
1.數據庫配置
DATABASES = {
'default': {
'ENGINE': 'django.db.backends.mysql',
'NAME': 'bbszikao',
'USER':'root',
'PASSWORD': 'root',
'HOST':'127.0.0.1',
'PORT':3306,
'CHARSET':'utf8'
}
}
2.靜態文件資源配置
STATICFILES_DIRS=[
os.path.join(BASE_DIR,'static')
]
3.models.py文件中,用戶表繼承AbstractUser類,需要對其進行settings配置
from django.contrib.auth.models import AbstractUser
配置auth模塊的訪問:
AUTH_USER_MODEL='app01.Userinfo'
4.靜態圖片資源settings配置+urls路由訪問配置,暴露給用戶查看,用戶注冊可以訪問到默認頭像
#settings文件配置:
MEDIA_ROOT=os.path.join(BASE_DIR,'media')
#urls文件訪問頭像路由配置
url(r'^media/(?P<path>.*)', serve, {'document_root': settings.MEDIA_ROOT}),
第三步功能開發
注冊功能
后端開發邏輯:
分為:register函數+register.html+myform.py文件
后端開發邏輯:
# myform.py 文件
1.建立myform.py文件,利用forms表單,提交注冊的數據信息
創建class MyRegForm(forms.Form):類
用戶名,密碼,確認密碼,郵箱
建立局部鈎子函數校驗用戶名是否存在
建立全局鈎子函數校驗密碼是否一致
# models.py 文件
2.把myform文件中的MyRegForm表單對象拿到,
然后把form_obj對象發送給前端register.html頁面
form_obj=myform.MyRegForm()
return render(request,'register.html',locals())
后端開發邏輯如下:
把myform文件中的MyRegForm表單對象拿到
判斷前端發送過來的請求方式是不是post請求
定義back_dic 字典
對用戶在前端提交的post數據進行校驗,生成form_obj對象
如果數據合法:
獲取鍵值對
pop掉確認密碼鍵值對
獲取前端發送的文件請求(avatar),創建文件對象
判斷用戶是否上傳文件:
上傳文件了,把avatar添加到clean_data字典對象中
用戶表創建用戶(create_user)
back_dic字典添加msg信息,注冊成功
back_dic字典添加url,login路徑
數據不合法:
字典添加code=2000
字典添加msg=form_obj.errors
返回json數據到前端,[需要導入JsonResponse模塊(from django.http import JsonResponse)]
然后把form_obj對象發送給前端register.html頁面
前端開發邏輯:
上傳頭像文件功能,注冊按鈕功能
前端開發邏輯:register.html文件,前端只整理需要整理的
上傳頭像文件功能
<script>
//上傳頭像文件相關的處理
$('#mdd').on('change',function () {
//利用內置對象filereader完成文件的讀取操作
let MyFileReader=new FileReader();
//獲取用戶上傳的文件對象
let fileobj=$(this)[0].files[0];
//讓文件閱讀器讀取文件,IO操作,異步
MyFileReader.readAsDataURL(fileobj);
//將讀取之后的內容替換到img標簽src屬性中
MyFileReader.onload=function () {
$('#img').attr('src',MyFileReader.result)
}
});
// 注冊按鈕
$('#submit').click(function () {
// 將用戶輸入的數據全部發送給后端 普通的鍵值對 文件
let MyFormData = new FormData();
// 不停的朝里面添加鍵值對
{#MyFormData.append('','')#}
{#console.log($('#myform').serializeArray())#}
// 普通鍵值對添加完畢 (利用form標簽內部有一個自動序列化普通鍵值對方法)
$.each($('#myform').serializeArray(),function (index,obj) {
MyFormData.append(obj.name,obj.value)
});
// 手動添加文件數據
MyFormData.append('avatar',$('#mdd')[0].files[0]);
// 發送ajax請求
$.ajax({
url:'',
type:'post',
data:MyFormData,
// 發送文件一定要指定兩個參數
processData:false, // 不要讓瀏覽器處理你的數據
contentType:false, // 不要使用任何的編碼 django能夠識別對象自身
success:function (data) {
if (data.code == 1000){
// 跳轉到登錄頁面
window.location.href = data.url
}else{
$.each(data.msg,function (index,obj) {
{#console.log(index,obj)#} // index就是報錯字段 obj就是錯誤信息 數組的形式
// 獲取報錯字段 手動拼接出該字段所對應的input框的id值
let targetId = '#id_' + index;
$(targetId).next().text(obj[0]).parent().addClass('has-error')
})
}
}
})
});
// input框獲取焦點事件,---這個是鼠標放到input框上面后,錯誤信息消失
$('input').focus(function () {
$(this).next().text('').parent().removeClass('has-error')
})
</script>
圖片驗證碼功能
后端開發邏輯
1.所需要的模塊
import random
from PIL import Image,ImageDraw,ImageFont
from io import BytesIO,StringIO
'''
內存管理器模塊:
BytesIO 保存數據,並且在獲取的時候,是以二進制的方式給你
StringIO 保存數據,並且在獲取的時候,是以字符串的方式給你
Image 生成圖片
ImageDraw 在圖片上寫字
ImageFont 控制字的字體樣式
'''
#io_obj=BytesIO() #你就將該對象看成是文件句柄即可
'''
什么是文件句柄???
在文件I/O中,要從一個文件讀取數據,應用程序首先
要調用操作系統函數並傳送文件名,並選一個到該文件
的路徑來打開文件。該函數取回一個順序號,即文件句柄
(file handle),該文件句柄對於打開的文件是唯一的
識別依據。要從文件中讀取一塊數據,應用程序需要調用
函數ReadFile,並將文件句柄在內存中的地址和要拷貝的
字節數傳送給操作系統。當完成任務后,再通過調用系統函數
來關閉該文件。”
'''
2.圖片驗證碼的開發分為兩步:
隨機取色+圖片驗證碼
2.1隨機取色
def get_random():
return random.randint(0,255),random.randint(0,255),random.randint(0,255)
2.2圖片驗證碼函數
圖片的寬高和隨機取色---生成畫板對象 Image.new
將生成好的圖片對象交給ImageDraw---畫筆對象 ImageDraw.Draw
字體樣式 ---何種字體 ImageFont.truetype
#隨機驗證碼 ---何種要求(大小寫英文加數字,5位)
定義code=''
循環5次:
大寫字母 upper_str
小寫字母 lower_str
str(隨機數) random_int
隨機選取一個,random.choice([大寫,小寫,str(隨機數)])
往圖片上寫一個驗證碼 img_draw.text
存儲寫的字 code+=tmp
將code存到session中,供全局函數訪問 request.session['code']=code
生成I/O文件句柄 io_obj=BytesIO()
圖片對象調用save方法保存io_obj文件對象,png的格式進行保存 img_obj.save(io_obj,'png')
return HttpResponse(io_obj.getvalue())
--------------------------------------------------------------------------------
3.圖片驗證碼代碼如下:
def get_code(request):
# 圖片的寬高和隨機取色 ----畫板
img_obj=Image.new('RGB',(360,35),get_random())
#將生成好的圖片對象交給ImageDraw ---畫筆
img_draw=ImageDraw.Draw(img_obj)
#字體樣式 ---何種字體
img_font=ImageFont.truetype('static/font/111.ttf',30)
#隨機驗證碼 ---何種要求(大小寫英文加數字,5位)
code=''
for i in range(5):
upper_str=chr(random.randint(65,90))
lower_str=chr(random.randint(97,122))
random_int=str(random.randint(0,9))
#隨機選取一個
tmp=random.choice([upper_str,lower_str,random_int])
#往圖片上寫一個驗證碼
img_draw.text((i*60+60,0),tmp,get_random(),img_font)
#存儲寫的字
code+=tmp
print(code)
#這個驗證碼后面其他視圖函數可能要用到,
#找個地方存一下,並且這個地方全局的視圖函數都能訪問
request.session['code']=code
io_obj=BytesIO() #你就將該對象看成是文件句柄即可
'''
在文件I/O中,要從一個文件讀取數據,應用程序首先
要調用操作系統函數並傳送文件名,並選一個到該文件
的路徑來打開文件。該函數取回一個順序號,即文件句柄
(file handle),該文件句柄對於打開的文件是唯一的
識別依據。要從文件中讀取一塊數據,應用程序需要調用
函數ReadFile,並將文件句柄在內存中的地址和要拷貝的
字節數傳送給操作系統。當完成任務后,再通過調用系統函數
來關閉該文件。”
'''
img_obj.save(io_obj,'png')
return HttpResponse(io_obj.getvalue())
圖片驗證碼實時刷新功能
前端開發邏輯
圖片驗證碼隨機變化的邏輯其實很簡單,就是:
首先為驗證碼綁定點擊事件,
其次拿到img中的src屬性,
最后為src設置新的值,使得圖片驗證碼不斷的更換
<div class="col-md-6">
<img src="/get_code/" alt="" width="360" height="35" id="id_img">
</div>
<script>
//拿到img中的src,
//然后為src設置新的值,使得圖片驗證碼不斷的更換
$('#id_img').click(function () {
var oldPath = $(this).attr('src');
$(this).attr('src',oldPath+='?')
});
</script>
登錄功能
后端開發邏輯
urls.py文件中:
# 登錄功能
url(r'^login/',views.login,name='login'),
views.py文件中:
開發邏輯如下:
如果請求方式是post請求:
定義back_dic
獲取post請求的用戶名
獲取post請求的密碼
獲取post請求的驗證碼
#先校驗驗證碼是否正確,忽略大小寫
#再校驗用戶名和密碼是否正確
如果用戶輸入的驗證碼和后端保存的驗證碼相等:
再用auth模塊校驗用戶名和密碼是否相等,生成用戶對象
如果相等:
利用auth模塊保存用戶對象的登錄狀態
#就可以在任意位置通過request.user獲取到當前登錄對象,並且request.user.is_authenticated()判斷當前用戶是否登錄
back_dic字典添加msg登錄成功
back_dic字典添加url,home主頁路徑
如果用戶名和密碼不相等:
back_dic字典添加code=2000
back_dic字典添加msg用戶名或密碼錯誤
如果驗證碼不相等:
back_dic字典添加code=3000
back_dic字典添加msg,驗證碼錯誤
通過JsonResponse返回字典
返回到登錄頁面
# 保存用戶登錄狀態,這個不太會,對該知識點模糊要多注意了,
# 通過auth模塊的login方法將用戶保存起來,就可以在任意位置通過request.user,
# 獲取到當前登錄對象,並且可以通過request.user.is_authenticated()判斷當前用戶是否登錄
auth.login(request, user_obj)
auth模塊很重要需要多復習復習
前端開發邏輯
為登錄按鈕綁定點擊事件,
利用ajax請求,把數據發送到后端
ajax的固定格式為:
$.ajax({
url:'',
type:'post',
data:{k,v鍵值對,'csrfmiddlewaretoken':'{{ csrf_token }}'},
success:function(data){
//此處的data就是后端返回過來的back_dic字典對象
如果code=1000:
跳轉到對應頁面的url連接
如果不等於1000:
渲染錯誤數據信息
信息錯誤后自動刷新驗證碼
}
})
提交post請求跳過csrf中間件攔截的兩種方式:
{% csrf_token %} ------- 在form表單中書寫
'csrfmiddlewaretoken':'{{ csrf_token }}' ------- 在ajax中的data字典中書寫
<div>
<input type="button" class="btn btn-primary" value="登錄" id="id_submit">
<span style="color: red;" id="id_error"></span> //在此處渲染頁面的錯誤信息
</div>
<script>
$('#id_submit').click(function () {
$.ajax({
url:'',
type:'post',
data:{
//$('#標簽名').val()是獲取當前標簽的值
'username':$('#id_username').val(),
'password':$('#id_password').val(),
'code':$('#id_code').val(),
'csrfmiddlewaretoken':'{{ csrf_token }}'
},
success:function (data) {
if(data.code == 1000){
// 跳轉鏈接
window.location.href = data.url
}else{
//渲染錯誤數據信息
$('#id_error').text(data.msg);
//數據填寫錯誤,提交后驗證碼再次刷新
var oldPath = $('#id_img').attr('src');
$('#id_img').attr('src',oldPath+='?')
}
}
})
</script>
首頁搭建功能
后端開發邏輯
#home主頁
第一步:查詢所有文章,生成文章queryset對象,
第二步:把數據全部提交到home頁面
def home(request):
#查詢所有文章,生成文章queryset對象,
#把數據全部提交到home頁面
article_queryset=models.Article.objects.all()
return render(request,'home.html',locals())
前端開發邏輯
主頁搭建共分為四塊,
第一塊,導航條
第二塊,左側面板 2
第三塊,中間面板 8
第四塊,右側面板 2
退出登錄功能
后端開發邏輯
導入auth模塊,導入登錄認證裝飾器:
from django.contrib import auth
from django.shortcuts import reverse
from django.contrib.auth.decorators import login_required
給退出登錄函數添加@login_required裝飾器,裝飾器不要加括號
利用auth模塊的退出登錄函數 ---auth.logout(request)
返回通過重定向反轉解析到home主頁 ---redirect(reversed('home'))
代碼如下:
@login_required
def logout(request):
auth.logout(request)
return redirect(reverse('home')) ---退出登錄之后跳轉到home主頁
注意事項,此處是reverse,可不要寫成reversed
前端開發邏輯
用戶登錄情況下:
展示用戶名:
拿到用戶的用戶名,------超鏈接;通過auth模塊的is_authenticated判斷用戶是否已經登錄
修改密碼
修改頭像
后台管理
退出登錄
未登錄情況下:
展示登錄 --超鏈接,反向解析login,{% url 'login' %}
展示注冊 --超鏈接,反向解析register,{% url 'register' %}
部分邏輯代碼如下:
{% if request.user.is_authenticated %}
<li><a href='#'> {{ request.user.username }} </a></li>
<li><a data-target="#myModal" data-toggle="modal">修改密碼</a></li>
<li><a href="#">修改頭像</a></li>
<li><a href="#">后台管理</a></li>
<li role="separator" class="divider"></li>
<li><a href="{% url 'logout' %}">退出登錄</a></li>
{% else %}
<li><a href="{% url 'login' %}">登錄</a></li>
<li><a href="{% url 'register' %}">注冊</a></li>
{% endif %}
修改密碼功能
后端開發邏輯
urls.py文件中開設修改密碼的路由
url(r'^set_password/',views.set_password,name='set_pwd')
views.py文件
from django.shortcuts import reverse
from django.contrib import auth
from django.contrib.auth.decorators import login_required
首先給修改密碼函數添加裝飾器@login_required
如果前端請求方式是post請求:
獲取前端發送過來的原密碼old_password
獲取前端發送過來的新密碼new_password
獲取前端發送過來的確認密碼confirm_password
#利用auth模塊先判斷前端發送過來的原密碼是否正確,
#check_password是auth模塊自帶的校驗密碼是否相等的功能
request.user.check_password(old_password)
如果原密碼正確:
如果新密碼和確認密碼相等:
利用auth模塊中的set_password設置新的密碼
然后利用auth模塊中的save方法進行保存
返回重定向解析到登錄頁面
如果新密碼和確認密碼不相等:
返回文本,兩次密碼不一致
如果原密碼不正確:
返回文本,原密碼錯誤
前端開發邏輯
利用form表單,發送post請求
反向解析到set_pwd路徑下,{% url 'set_pwd' %}
利用{% csrf_token %} 跳過csrf中間件
下面就是form表單中的5個div,分別是:
用戶名,使用disable屬性,默認展示用戶名不支持修改
原密碼
新密碼
確認密碼
取消,修改