1. 程式人生 > >DAY88-BBS專案(二) 註冊

DAY88-BBS專案(二) 註冊

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">頭像&nbsp;&nbsp;&nbsp;&nbsp;
                        <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會自動建立)