Django - BBS 项目学习 - 注册功能页面的实现(forms组件)

目录

一、myforms.py - forms组件设计

二、 views.py - 视图函数处理传输数据

三、register.html - 前端


一、myforms.py - forms组件设计

注意知识点:

  • 局部钩子命名方式必须为:clean_类内属性名
  • 全局钩子命名方式必须为:clean  ---- 即重写clean方法
from django import forms
from django.forms import widgets
from bbs import models
from django.core.exceptions import ValidationError


class MyForm(forms.Form):
    username = forms.CharField(
        max_length=18, min_length=2, label='用户名',

        widget=widgets.TextInput(attrs={'class': 'form-control',
                                        'placeholder': "请输入用户名"}),
        error_messages={'max_length': '长度不大于18',
                        'min_length': '长度不小于2',
                        'required': '必填选项',
                        }
    )
    password = forms.CharField(
        max_length=18, min_length=2, label='密码',
        widget=widgets.PasswordInput(attrs={'class': 'form-control',
                                            'placeholder': "请输入密码"}),
        error_messages={'max_length': '长度不大于18',
                        'min_length': '长度不小于2',
                        'required': '必填选项',
                        }
    )
    re_password = forms.CharField(
        max_length=18, min_length=2, label='确认密码',
        widget=widgets.PasswordInput(attrs={'class': 'form-control',
                                            'placeholder': "请确认密码"}),
        error_messages={'max_length': '长度不大于18',
                        'min_length': '长度不小于2',
                        'required': '必填选项',
                        }
    )
    email = forms.CharField(
        label='邮箱',
        widget=widgets.EmailInput(attrs={'class': 'form-control',
                                         'placeholder': "请输入邮箱"}),
        error_messages={
            'invalid':'格式不合法',
            'required': '必填选项',
        }
    )

    # 用户名存在校验
    def clean_username(self):
        name = self.cleaned_data.get('username')
        valid = models.UserInfo.objects.filter(username=name).first()
        if valid:
            raise ValidationError('用户名已存在')
        return name

    # 密码确认校验
    def clean(self):
        pwd = self.cleaned_data.get('password')
        re_pwd = self.cleaned_data.get('re_password')
        if pwd == re_pwd:
            return self.cleaned_data
        else:
            raise ValidationError('两次密码不一致')

二、 views.py - 视图函数处理传输数据

注意知识点:

  • 使用forms组件必须导入自定义的form文件
  • 必须在视图函数内建立对应form对象
    myform = myforms.MyForm()
  • 习惯设置返回字典
    response = {'status': 200, 'msg': None}
  • 进行数据库ORM操作时,若选择使用**快捷填入,必须将forms自定属性和数据库内字段名完全一致
    user = models.UserInfo.objects.create_user(**dic)
  • forms组件进行判断之后,所有数据放在cleaned_data属性内
  • forms组件进行判断之后,报错信息放在errors属性内
     
from django.shortcuts import render, HttpResponse
from django.http import JsonResponse
from bbs import myforms
from bbs import models



def register(request):
    '''
    注册功能
        - 使用forms组件进行验证
    :param request:
    :return:
    '''
    if request.method == 'GET':
        myform = myforms.MyForm()
        return render(request, 'register.html', locals())

    elif request.is_ajax():
        # 设置返回对象,200默认成功
        response = {'status': 200, 'msg': None}
        myform = myforms.MyForm(request.POST)
        print(myform.errors)
        if myform.is_valid():
            dic = myform.cleaned_data
            dic.pop('re_password')
            my_file = request.FILES.get('my_file')
            if my_file:
                dic['avatar'] = my_file
            # 使用**dic进行传值,必须保证dic内的key值和数据库内的字段名完全相同
            # 即自定义forms内类属性和数据库内字段名完全相同
            # 注意数据库内头像字段的属性为FileField 时,只要传入对象就可以进行自动处理数据保存
            user = models.UserInfo.objects.create_user(**dic)
        else:
            response['status'] =None
            response['msg'] = myform.errors

        return JsonResponse(response)

三、register.html - 前端

注意知识点:

  • 注意必须带上{% csrf_token %}进行传输
  • 可使用循环对视图函数传输的myform对象进行循环渲染
    • for="{{ foo.auto_id }}” -- 用于对应相应label
    • {{ foo.label }} -- 属性label名,在forms类内自定
    • {{foo}} -- 属性的值,根据forms内属性widget进行渲染
    • {{foo.errors.0}} -- 属性的值,根据forms内的错误信息进行渲染
  • 将头像文件的选择项隐藏在图片显示框后,可实现点击图片选择文件

     

    • <div>
          <label for="my_file">头像
              <img src="/static/img/default.png" id="img_file">
          </label>
          <input type="file" id="my_file" style="display: none">
      </div>

  • 使用jq实现当文件选择项发生变化,触发图像放置框内图像文件的改变
    {#当头像文件发生变化,触发页面img显示为放入的图像文件#}
        $('#my_file').change(function () {
            var file_obj = $('#my_file')[0].files[0];
            var filereader = new FileReader();//文件阅读器对象生成,将图片放到img标签上
    
            {# 获取图片对象的地址,放入filereader.result #}
            filereader.readAsDataURL(file_obj);
            {# 必须等路径加载完成后才能进行渲染操作 #}
            filereader.onload = function () {
                $('#img_file').attr('src', filereader.result)
            }
        })

     

  • ajax使用formdata对象放入数据时候,可使用serializeArray()方法+循环放入
     var formdata = new FormData();
    {# 将form表单内内容打包,转成对象(列表套字典) #}
    var arr = $('#form').serializeArray();
    {#console.log(arr);#}
    {# 循环将arr内对象放入formdata内 #}
    $.each(arr, function (k, obj) {
       {#console.log(k);#}
       {#console.log(obj);#}
       formdata.append(obj.name, obj.value);
    });
    {# formdata添加文件对象 #}
    formdata.append('my_file', $('#my_file')[0].files[0]);

  • 使用jq的each能实现循环操作
  • 清除页面上原有的错误信息
    $(".error_right").html("");
    $(".error_right").parent().removeClass("has-error");
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <link rel="stylesheet" href="/static/bootstrap-3.3.7-dist/css/bootstrap.min.css">
    <script src="/static/jquery-3.3.1.js"></script>
    <title>注册</title>
</head>
<style>
    .has-error {
        color: red;
    }

    #img_file {
        width: 80px;
        height: 80px;
        margin-left: 10px;
    }
</style>
<body>
<div class="container-fluid">
    <div class="row">
        <div class="col-md-6 col-md-offset-3">
            <h1>注册</h1>
            <form id="form">
                {% csrf_token %}
                {% for foo in myform %}
                    <div class="form-group">
                        <label for="{{ foo.auto_id }}">{{ foo.label }}</label>
                        {{ foo }}
                    </div>
                {% endfor %}
                <div>
                    <label for="my_file">头像
                        <img src="/static/img/default.png" id="img_file">
                    </label>
                   {# accept='image/*'只允许显示所有图片格式文件 #}
                    <input accept='image/*'type="file" id="my_file" style="display: none">
                </div>
                <input type="button" id='btn' value="注册" class="btn btn-primary pull-right">
            </form>

        </div>

    </div>

</div>
</body>
<script>

    {#当头像文件发生变化,触发页面img显示为放入的图像文件#}
    $('#my_file').change(function () {
        var file_obj = $('#my_file')[0].files[0];
        var filereader = new FileReader();//文件阅读器对象生成,将图片放到img标签上

        {# 获取图片对象的地址,放入filereader.result #}
        filereader.readAsDataURL(file_obj);
        {# 必须等路径加载完成后才能进行渲染操作 #}
        filereader.onload = function () {
            $('#img_file').attr('src', filereader.result)
        }
    })
    {#    实现ajax传输数据给后台#}
    $('#btn').click(function () {
        var formdata = new FormData();
        {# 将form表单内内容打包,转成对象(列表套字典) #}
        var arr = $('#form').serializeArray();
        {#console.log(arr);#}
        {# 循环将arr内对象放入formdata内 #}
        $.each(arr, function (k, obj) {
            {#console.log(k);#}
            {#console.log(obj);#}
            formdata.append(obj.name, obj.value);
        });
        {# formdata添加文件对象 #}
        formdata.append('my_file', $('#my_file')[0].files[0]);

        $(".error_right").html("");
        $(".error_right").parent().removeClass("has-error");
        $.ajax({
            url: '/register/',
            type: 'post',
            data: formdata,
            processData: false,
            contentType: false,
            success: function (data) {
                if (data['status']) {
                    location.href = '/index/'
                }
                else {
                    console.log(data['msg']);
                    var msg = data['msg'];
                    $.each(msg, function (k, v) {
                        console.log(msg)
                        $span = $('<span>');
                        $span.addClass('error_right').css("color", 'red');
                        $span.html(v[0]);
                        $('#id_' + k).after($span).parent().addClass('has-error');

                        if (k == '__all__') {

                            $("#btn").after($span);



                        }
                    });
                }
            }
        })
    });
</script>

</html>

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值