DAY88-BBS專案(二) 註冊
阿新 • • 發佈:2018-11-28
BBS之註冊功能
前端
模板層
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>登入</title> {% load static %} <link rel="stylesheet" href="{% get_static_prefix %}bootstrap-3.3.7-dist/css/bootstrap.css"> <script src="{% get_static_prefix %}jquery-3.3.1.js"></script> </head> <body> <div class="container-fluid"> <div class="row"> <div class="col-md-4 col-md-offset-4 bg-success clearfix img-rounded" style="padding-bottom: 30px"> <h1 style="text-align: center">註冊</h1> <form id="reg_form" novalidate> {% csrf_token %} {% for foo in my_form %} <div class="form-group"> <label for="{{ foo.auto_id }}">{{ foo.label }}</label><span style="color: red;" id="error" class="pull-right"></span> {{ foo }} </div> {% endfor %} <div class="form-group"> <label for="my_file">頭像 <img src="/static/image/default.png" alt="" id="picture" width="80" height="80"> </label> <input type="file" class="hidden" id="my_file" required> </div> </form> <span style="margin-left: 230px;color: red" id="msg"></span> <button type="button" class="btn btn-info btn-lg pull-right active " id="btn">註冊</button> </div> </div> </div> </body> <script> $('#my_file').change(function () { // 先獲得圖片$('#my_file')[0].files[0],生成圖片物件file var file = $(this)[0].files[0]; // 生成一個檔案閱讀器 var read = new FileReader(); // 檔案閱讀器讀入圖片 read.readAsDataURL(file); // 由於圖片是屬於頁面資源,必須等頁面載入完才顯示圖片 read.onload = function () { $('#picture').attr('src', read.result) } }) $('#btn').click(function () { var formdata = new FormData(); // 呼叫表單的serializeArray()方法序列化表單元素,以列表套字典[{name: "username", value: ""},.....] var arrt = $('#reg_form').serializeArray(); // $.each(被迴圈的,迴圈體(匿名函式)):JQ的迴圈方法 $.each(arrt, function (index, data) { formdata.append(data.name, data.value) }) // 單獨新增檔案 formdata.append('my_file', $('#my_file')[0].files[0]); $.ajax({ url: '/register/', type: 'post', processData: false, contentType: false, data: formdata, success: function (data) { if (data.status == '200') { $('#msg').text('註冊成功') } else if (data.status == '404') { $('#msg').text('頭像上傳失敗') } else if (data.status == '401') { // data.error得到的是錯誤資訊,字典套列表{'username':[錯誤資訊]..},迴圈得到key值 for (let i in data.error) { // 迴圈判斷錯誤的是那些 $.each(arrt, function (index, value) { if (i == value.name) { // 把input的前一個同輩標籤span的text變成錯誤資訊data.error[i][0] $('#id_' + i).prev('span').text(data.error[i][0]) } }) } // 如果有全域性錯誤資訊,顯示到$('#msg').text(data.error['__all__']) if (data.error['__all__']) { $('#msg').text(data.error['__all__']) } } } }) }) </script> </html>
後端
forms元件
from django import forms from django.forms import widgets from blog.models import UserInfo from django.core.exceptions import ValidationError class User_from(forms.Form): username = forms.CharField(label='使用者名稱', max_length=10, min_length=3,widget=widgets.TextInput(attrs={'class': 'form-control'}),error_messages={'max_length': '最長是19', 'min_length': '最短是3', 'required': '不能為空'}, ) password = forms.CharField(label='密碼', max_length=10, min_length=3,widget=widgets.PasswordInput(attrs={'class': 'form-control'}),error_messages={'max_length': '最長是0', 'min_length': '最短是3', 'required': '不能為空'}) re_password = forms.CharField(label='確認密碼', max_length=10, min_length=3,widget=widgets.PasswordInput(attrs={'class': 'form-control'}),error_messages={'max_length': '最長是10', 'min_length': '最短是3', 'required': '不能為空'}) email = forms.EmailField(label='郵箱', error_messages={'required': '不能為空','invalid': '不符合郵箱格式'},widget=widgets.EmailInput(attrs={'class': 'form-control'})) def clean_username(self): name = self.cleaned_data.get('username') name_db = UserInfo.objects.filter(username=name).first() if name_db: raise ValidationError('使用者已存在') return name def clean(self): pwd = self.cleaned_data.get('password') re_pwd = self.cleaned_data.get('re_password') if pwd and re_pwd: if pwd != re_pwd: raise ValidationError('兩次密碼不一致') return self.cleaned_data
檢視層
from django.shortcuts import render, HttpResponse from django.http import JsonResponse from blog import myform from blog.models import UserInfo def register(requset): response = {'status': 200, 'error': None} if requset.method == 'POST': # 將所有POST資料放入放入form元件驗證 my_form = myform.User_from(requset.POST) # 驗證通過 if my_form.is_valid(): # 將驗證通過的資料放到dic裡 dic = my_form.cleaned_data # 去除不需要存入資料庫的re_password dic.pop('re_password') # 獲得檔案 my_file = requset.FILES.get('my_file') # 為了區分頭像,加上字首 my_file.name = requset.POST.get('username') + '_' + my_file.name if my_file: # 在dic中新增頭像資料 dic['avatar'] = my_file # 建立使用者 UserInfo.objects.create_user(**dic) else: response['status'] = 404 else: response['status'] = 401 response['error'] = my_form.errors return JsonResponse(response) my_form = myform.User_from() return render(requset, 'register.html', locals())
總結
基於forms元件和Ajax實現註冊功能
# 1 基於forms元件設計註冊頁面
---點選頭像===點選input
---頭像預覽:
1 獲取使用者選中的檔案物件
2 獲取檔案物件的路徑
3 修改img的src屬性 ,src=檔案物件的路徑
# 2 錯誤資訊:
// data.error得到的是錯誤資訊,字典套列表{'username':[錯誤資訊]..},迴圈得到key值
for (let i in data.error) {
// 迴圈判斷錯誤的是那些
$.each(arrt, function (index, value) {
if (i == value.name) {
// 把input的前一個同輩標籤span的text變成錯誤資訊data.error[i][0]
$('#id_' + i).prev('span').text(data.error[i][0])
}
})
}
// 如果有全域性錯誤資訊,顯示$('#msg').text(data.error['__all__'])
if (data.error['__all__']) {
$('#msg').text(data.error['__all__'])
}
# 3 區域性鉤子和全域性鉤子校驗
user欄位不能重複
兩次密碼不一致
# 4 FileField與ImageFiled
區別是:
fileField是可以任何檔案
ImageFile只能是圖片檔案
class UserInfo(AbstractUser):
nid = models.AutoField(primary_key=True)
# 電話可以為空
phone = models.CharField(max_length=32, null=True)
# 頭像
avatar = models.FileField(upload_to='static/avatar/', default='/static/image/default.png')
# 站點
blog = models.OneToOneField(to='Blog', to_field='nid',null=True)
Dajngo實現:
會將檔案物件下載到專案中avatars資料夾中(如果沒有avatar資料夾,Django會自動建立)