3.注册功能

Forms组件代码书写

复制代码
"""
我们之前直接在views.py中书写forms组件代码
但是为了解耦合,应当将所有的forms组件代码单独写到一个地方

如果项目自始至终只用到一个forms组件,那么可以直接建一个py文件即可(bbs项目使用该方法,在应用下创建)
    myforms.py
如果你的项目需要用到多个forms组件,那么可以创建一个文件夹并在该文件夹内根据forms组件功能的不同创建不同的py文件
    myforms文件夹
        regform.py
        loginform.py
        userform.py
"""
复制代码
复制代码
# 书写针对用户表的forms组件代码

from django import forms

class MyRegForm(forms.Form):
    username = forms.CharField(label='用户名', min_length=3, max_length=8,
                               error_messages={
                                   'required': '用户名不能为空',
                                   'min_length': '用户名最少3位',
                                   'max_length': '用户名最多8位'
                               },
                               # 还要让标签有bootstrap样式
                               widget=forms.widgets.TextInput(attrs={'class': 'form-control'})
                               )
    password = forms.CharField(label='密码', min_length=3, max_length=8,
                               error_messages={
                                   'required': '密码不能为空',
                                   'min_length': '密码最少3位',
                                   'max_length': '密码最多5位'
                               },
                               # 还要让标签有bootstrap样式
                               widget=forms.widgets.PasswordInput(attrs={'class': 'form-control'})
                               )
    confirm_password = forms.CharField(label='确认密码', min_length=3, max_length=8,
                                       error_messages={
                                           'required': '密码不能为空',
                                           'min_length': '密码最少3位',
                                           'max_length': '密码最多8位'
                                       },
                                       # 还要让标签有bootstrap样式
                                       widget=forms.widgets.PasswordInput(attrs={'class': 'form-control'})
                                       )
    email = forms.CharField(label='邮箱',
                            error_messages={
                                'required': '邮箱不能为空',
                                'invalid': '邮箱格式不正确'
                            },
                            )

    # 局部钩子
    def clean_username(self):
        # 获取到用户名
        username = self.cleaned_data.get('username')
        # 数据通过了form组件条件的数据都会存储在cleaned_data里,所以我们拿出这里面(过了第一道关卡)的数据,进行添加第二道关卡
        if 'yuan' in username:
            # 提示前端展示错误信息
            self.add_error('username', '用户名不能存在yuan')
        # 将钩子函数勾出来的数据再放回去
        return username

    # 全局钩子
    def clean(self):
        password = self.cleaned_data.get('password')
        confirm_password = self.cleaned_data.get('confirm_password')
        if not password == confirm_password:
            self.add_error('confirm_password', '两次密码不一致')
        return self.cleaned_data
myforms.py
复制代码

注册页面简易搭建

复制代码
<body>
<div class="container-fluid">
    <div class="row">
        <div class="col-xs-8 col-xs-offset-2">
            <form id="myform">
                {% csrf_token %}
                <h1 class="text-center">注册</h1>
                {% for form in form_obj %}
                        <div class="form-group">
                            <label for="">{{ form.label }}</label>
                            {{ form }}  <!--form_obj是forms组件渲染的html页面-->
                            <span>{{ form.errors.0 }}</span>
                        </div>
                    {% endfor %}
                    <div class="form-group">
                        <label for="">头像</label>
                        <input type="file" id="myfile" name="avatar">
                        {% load static %}
                        <img src="{% static '/img/default.png' %}" alt="" id="myimg" width="50px" style="margin-left: 10px">
                    </div>
                <input type="button" class="btn btn-primary pull-right" value="注册" id="id_commit">
            </form>
        </div>
    </div>
</div>
</body>
register.html
复制代码

用户头像实时展示

  优化点一

# 创建一个static文件夹,该文件夹下创建一个img文件夹,在该文件夹下存放一张默认的头像图片
    --static
        --img
            default.png
# 添加代码
    {% load static %}
    <img src="{% static 'img/default.png' %}" alt=""  id='myimg' width="50px" style="margin-left: 10px">

  优化点二

  优化点三

当更换头像时,会在浏览器上实时更新你所更换的图片

复制代码
<script>
    $('#myfile').change(function(){
        // 文件阅读器对象
        // 1.先生成一个文件阅读器对象
        let myFileReaderObj = new FileReader()
        // 2.获取用户上传的头像文件
        let fileObj = $(this)[0].files[0];
        // 3.将文件对象交给阅读器对象读取
        myFileReaderObj.readAsDataURL(fileObj)
        // 4.利用文件阅读器将文件展示到前端页面  修改图片img的src属性
        $('#myimg').attr('src',myFileReaderObj.result)
    })
</script>
View Code
复制代码

由于myFileReaderObj.readAsDataURL(fileObj)是一个异步操作,该代码执行完之后,不会等待文件阅读完毕就执行下面的操作,所以展示的图片为空

解决方案:等待文件阅读器加载之后再执行(等待某某执行之后再执行在js中使用 onload )

复制代码
<script>
    $('#myfile').change(function(){
        // 文件阅读器对象
        // 1.先生成一个文件阅读器对象
        let myFileReaderObj = new FileReader()
        // 2.获取用户上传的头像文件
        let fileObj = $(this)[0].files[0];
        // 3.将文件对象交给阅读器对象读取
        myFileReaderObj.readAsDataURL(fileObj)  // 异步操作 IO操作
        // 4.利用文件阅读器将文件展示到前端页面  修改图片的src属性
        // 等待文件阅读器加载完毕之后再执行(等待某某执行之后再执行  使用onload)
        myFileReaderObj.onload = function(){
             $('#myimg').attr('src',myFileReaderObj.result)
        }
    })
</script>
register.html.script
复制代码

注册功能的初步实现

 

 

复制代码
<script>
    $('#myfile').change(function(){
        // 文件阅读器对象
        // 1.先生成一个文件阅读器对象
        let myFileReaderObj = new FileReader()
        // 2.获取用户上传的头像文件
        let fileObj = $(this)[0].files[0];
        // 3.将文件对象交给阅读器对象读取
        myFileReaderObj.readAsDataURL(fileObj)  // 异步操作 IO操作
        // 4.利用文件阅读器将文件展示到前端页面  修改图片的src属性
        // 等待文件阅读器加载完毕之后再执行(等待某某执行之后再执行  使用onload)
        myFileReaderObj.onload = function(){
             $('#myimg').attr('src',myFileReaderObj.result)
        }
    })

    $('#id_commit').click(function(){
        // 发送ajax请求  我们发送的数据中既包含普通的键值对也包含文件
        let FormDataObj = new FormData()
        // 1.添加普通的键值对
        {#console.log($('#myform').serializeArray())  // [{},{},{},{},{}]只包含普通键值对#}
        $.each($('#myform').serializeArray(),function (index,obj){
            {#console.log(index,obj)  // index是索引 obj为一个个对象{name: 'username', value: 'jiang'}#}
            FormDataObj.append(obj.name,obj.value)
        })

        // 2.添加文件数据
        FormDataObj.append('avatar',$('#myfile')[0].files[0])

        // 3.发送ajax请求
        $.ajax({
            url:'',
            type:'post',
            data:FormDataObj,
            // 需要指定两个关键性的参数
            contentType:false,
            processData:false,

            success:function(args){
                if (args.code==1000){
                    // 跳转到登陆界面
                    window.location.href = args.url
                }else{
                    // 如何将对应的错误提示展示到对应的input框下面
                    // forms组件渲染的标签的id值都是 id_字段名
                    $.each(args.msg,function (index,obj) {
                        {#console.log(index,obj)  //  username        ["用户名不能为空"]#}
                        let targetId = '#id_' + index;
                        $(targetId).next().text(obj[0]).parent().addClass('has-error')
                    })
                }
            }
        })
    })
</script>
register.html.script
复制代码
复制代码
from django.shortcuts import render
from app01.myforms import MyRegForm
from app01 import models
from django.http import JsonResponse


def register1(request):
    form_obj = MyRegForm()
    if request.method == 'POST':
        back_dic = {'code':1000,'msg':''}
        # 校验数据是否合法
        form_obj = MyRegForm(request.POST)
        # 判断数据是否合法
        if form_obj.is_valid():
            # print(form_obj.cleaned_data)  # {'username': 'jiang', 'password': '123', 'confirm_password': '123', 'email': '2573013863@qq.com'}
            clean_data = form_obj.cleaned_data  # 将校验通过的数据字典赋值给一个变量
            # 将字典里面的confirm_password键值对删除(是为了将数据保存在数据中,所以confirm_password不需要)
            clean_data.pop('confirm_password')  # {'username': 'jiang', 'password': '123', 'email': '2573013863@qq.com'}
            # 用户头像
            file_obj = request.FILES.get('avatar')
            """针对用户头像一定要判断是否传值 不能直接添加到字典里面去"""
            if file_obj:
                clean_data['avatar'] = file_obj
            # 直接操作数据库保存数据
            models.UserInfo.objects.create_user(**clean_data)
            back_dic['url'] = '/login/'
        else:
            back_dic['code'] = 2000
            back_dic['msg'] = form_obj.errors
        return JsonResponse(back_dic)
    return render(request,'register1.html',locals())
views.py
复制代码

给所有的input框绑定获取焦点事件

复制代码
<script>
    // 给所有的input框绑定获取焦点事件
    $('input').focus(function () {
        // 将input下面的span标签和input外面的div标签修改内容及属性
        $(this).next().text('').parent().removeClass('has-error')
    })
</script>
register.html.script
复制代码

注册功能

复制代码
from django.contrib import admin
from django.urls import path,re_path
from app01 import views

urlpatterns = [
    path('admin/', admin.site.urls),
    # 注册页面
    re_path(r'^register1/', views.register),
]
urls.py
复制代码
复制代码
# 书写针对用户表的forms组件代码


from django import forms
from app01 import models


class MyRegForm(forms.Form):
    username = forms.CharField(label='用户名', min_length=3, max_length=8,
                               error_messages={
                                   'required': '用户名不能为空',
                                   'min_length': '用户名最少3位',
                                   'max_length': '用户名最多8位'
                               },
                               # 还要让标签有bootstrap样式
                               widget=forms.widgets.TextInput(attrs={'class': 'form-control'})
                               )
    password = forms.CharField(label='密码', min_length=3, max_length=8,
                               error_messages={
                                   'required': '密码不能为空',
                                   'min_length': '密码最少3位',
                                   'max_length': '密码最多5位'
                               },
                               # 还要让标签有bootstrap样式
                               widget=forms.widgets.PasswordInput(attrs={'class': 'form-control'})
                               )
    confirm_password = forms.CharField(label='确认密码', min_length=3, max_length=8,
                                       error_messages={
                                           'required': '密码不能为空',
                                           'min_length': '密码最少3位',
                                           'max_length': '密码最多8位'
                                       },
                                       # 还要让标签有bootstrap样式
                                       widget=forms.widgets.PasswordInput(attrs={'class': 'form-control'})
                                       )
    email = forms.CharField(label='邮箱',
                            error_messages={
                                'required': '邮箱不能为空',
                                'invalid': '邮箱格式不正确'
                            },
                            )

    # 局部钩子
    def clean_username(self):
        # 获取到用户名
        username = self.cleaned_data.get('username')
        # 数据通过了form组件条件的数据都会存储在cleaned_data里,所以我们拿出这里面(过了第一道关卡)的数据,进行添加第二道关卡
        if 'yuan' in username:
            # 提示前端展示错误信息
            self.add_error('username', '用户名不能存在yuan')
        # 将钩子函数勾出来的数据再放回去
        return username

    # 全局钩子
    def clean(self):
        password = self.cleaned_data.get('password')
        confirm_password = self.cleaned_data.get('confirm_password')
        if not password == confirm_password:
            self.add_error('confirm_password', '两次密码不一致')
        return self.cleaned_data
myforms.py
复制代码
复制代码
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
    <meta name="viewport" content="width=device-width, initial-scale=1">
    <link href="https://cdn.bootcss.com/twitter-bootstrap/3.4.1/css/bootstrap.min.css" rel="stylesheet">
    <script src="https://cdn.bootcss.com/jquery/3.3.1/jquery.min.js"></script>
    <script src="https://cdn.bootcss.com/twitter-bootstrap/3.4.1/js/bootstrap.min.js"></script>
</head>
<body>
<div class="container-fluid">
    <div class="row">
        <div class="col-md-8 col-md-offset-2">
            <h1 class="text-center">注册</h1>
            <form id="myform">  <!--这里我们不用form表单提交数据 知识单纯的用一下form标签而已-->
                {% csrf_token %}
                {% for form in form_obj %}
                    <div class="form-group">
                        <label for="{{ form.auto_id }}">{{ form.label }}</label>
                        {{ form }}
                        <span style="color: red">{{ form.errors.0 }}</span>
                        <span style="color: red"></span>
                    </div>
                {% endfor %}
                <div class="form-group">
                    <label for="myfile">头像
                        {% load static %}
                        <img src="{% static 'img/default.png' %}" alt=""  id='myimg' alt="" width="50" style="margin-left: 10px">
                    </label>
                    <input type="file" id="myfile" name="avatar" style="display: none">
                </div>
                <input type="button" class="btn btn-primary pull-right" value="注册" id="id_commit">
            </form>
        </div>
    </div>
</div>

<script>
    $('#myfile').change(function(){
        // 文件阅读器对象
        // 1.先生成一个文件阅读器对象
        let myFileReaderObj = new FileReader()
        // 2.获取用户上传的头像文件
        let fileObj = $(this)[0].files[0];
        // 3.将文件对象交给阅读器对象读取
        myFileReaderObj.readAsDataURL(fileObj)  // 异步操作 IO操作
        // 4.利用文件阅读器将文件展示到前端页面  修改图片的src属性
        // 等待文件阅读器加载完毕之后再执行(等待某某执行之后再执行  使用onload)
        myFileReaderObj.onload = function(){
             $('#myimg').attr('src',myFileReaderObj.result)
        }
    })

    $('#id_commit').click(function(){
        // 发送ajax请求  我们发送的数据中既包含普通的键值对也包含文件
        let FormDataObj = new FormData()
        // 1.添加普通的键值对
        {#console.log($('#myform').serializeArray())  // [{},{},{},{},{}]只包含普通键值对#}
        $.each($('#myform').serializeArray(),function (index,obj){
            {#console.log(index,obj)  // index是索引 obj为一个个对象{name: 'username', value: 'jiang'}#}
            FormDataObj.append(obj.name,obj.value)
        })

        // 2.添加文件数据
        FormDataObj.append('avatar',$('#myfile')[0].files[0])

        // 3.发送ajax请求
        $.ajax({
            url:'',
            type:'post',
            data:FormDataObj,
            // 需要指定两个关键性的参数
            contentType:false,
            processData:false,

            success:function(args){
                if (args.code==1000){
                    // 跳转到登陆界面
                    window.location.href = args.url
                }else{
                    // 如何将对应的错误提示展示到对应的input框下面
                    // forms组件渲染的标签的id值都是 id_字段名
                    $.each(args.msg,function (index,obj) {
                        {#console.log(index,obj)  //  username        ["用户名不能为空"]#}
                        let targetId = '#id_' + index;
                        $(targetId).next().text(obj[0]).parent().addClass('has-error')
                    })
                }
            }
        })
    })
    // 给所有的input框绑定获取焦点事件
    $('input').focus(function () {
        // 将input下面的span标签和input外面的div标签修改内容及属性
        $(this).next().text('').parent().removeClass('has-error')
    })
</script>
</body>
</html>
register.html
复制代码
复制代码
from django.shortcuts import render
from app01.myforms import MyRegForm
from app01 import models
from django.http import JsonResponse
# Create your views here.


def register(request):
    form_obj = MyRegForm()
    if request.method == 'POST':
        back_dic = {'code':1000,'msg':''}
        # 校验数据是否合法
        form_obj = MyRegForm(request.POST)
        # 判断数据是否合法
        if form_obj.is_valid():
            # print(form_obj.cleaned_data)  # {'username': 'jiang', 'password': '123', 'confirm_password': '123', 'email': '2573013863@qq.com'}
            clean_data = form_obj.cleaned_data  # 将校验通过的数据字典赋值给一个变量
            # 将字典里面的confirm_password键值对删除(是为了将数据保存在数据中,所以confirm_password不需要)
            clean_data.pop('confirm_password')  # {'username': 'jiang', 'password': '123', 'email': '2573013863@qq.com'}
            # 用户头像
            file_obj = request.FILES.get('avatar')
            """针对用户头像一定要判断是否传值 不能直接添加到字典里面去"""
            if file_obj:
                clean_data['avatar'] = file_obj
            # 直接操作数据库保存数据
            models.UserInfo.objects.create_user(**clean_data)
            back_dic['url'] = '/login/'
        else:
            back_dic['code'] = 2000
            back_dic['msg'] = form_obj.errors
        return JsonResponse(back_dic)
    return render(request,'register.html',locals())
views.py
复制代码

 

posted @   猿小姜  阅读(14)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· 分享一个免费、快速、无限量使用的满血 DeepSeek R1 模型,支持深度思考和联网搜索!
· 基于 Docker 搭建 FRP 内网穿透开源项目(很简单哒)
· 25岁的心里话
· ollama系列01:轻松3步本地部署deepseek,普通电脑可用
· 按钮权限的设计及实现
点击右上角即可分享
微信分享提示