zoukankan      html  css  js  c++  java
  • Django 实现注册时选择头像,头像预览在页面,并且在数据库中写入头像文件,Ajax参数及上传文件方式

    使用场景:用户注册等

    1、表结构

    class UserInfo(AbstractUser):
        """
        用户信息表,继承auth认证模块中的默认表
        """
        nid = models.AutoField(primary_key=True)
        phone = models.CharField(max_length=11, unique=True)
        avatar = models.FileField(upload_to='static/img', default='static/img/default.png', verbose_name='头像')  #upload_to值为头像存在本地的地址
        create_time = models.DateTimeField(auto_now_add=True)  # 注册时间
    
        class Meta:
            verbose_name = '用户表'
            verbose_name_plural = verbose_name
    
        def __str__(self):
            return self.username

    2、forms表单验证注册

    from django import forms
    from blog import models
    from django.contrib.auth.backends import ModelBackend
    from django.db.models import Q
    from .models import UserInfo
    
    
    from django.core.validators import RegexValidator
    from django.core.exceptions import ValidationError
    
    """
    注册页表单
    """
    
    class Register(forms.Form):
        username = forms.CharField(max_length=15, min_length=2,
                                   label='用户名',
                                   error_messages={
                                       'max_length': '最长不能超过15位',
                                       'min_length': '最短不能少于2位',
                                       'required': '用户名不能为空'
                                   },
                                   widget=forms.widgets.TextInput(
                                       attrs={"class": "form-control"},
                                   )
                                   )
    
        password = forms.CharField(min_length=6,
                                   label='密码',
                                   error_messages={
                                       'min_length': '密码长度小于6',
                                       'required': '密码不能为空'
                                   },
                                   widget=forms.widgets.PasswordInput(
                                       attrs={"class": "form-control"},
                                   )
                                   )
    
        rep_password = forms.CharField(min_length=6,
                                       label='确认密码',
                                       error_messages={
                                           'min_length': '确认密码长度小于6',
                                           'required': '确认密码不能为空'
                                       },
                                       widget=forms.widgets.PasswordInput(
                                           attrs={"class": "form-control"},
                                       )
                                       )
    
        email = forms.EmailField(label='邮箱',
                                 error_messages={
                                     'invalid': '邮箱格式不正确',
                                     'required': '邮箱不能为空'
                                 },
                                 widget=forms.widgets.EmailInput(
                                     attrs={"class": "form-control"},
                                 )
                                 )
    
        phone = forms.CharField(  # max_length=11,
            label='手机号',
            validators=[RegexValidator(r'^[0-9]+$', '请输入数字'),
                        RegexValidator(r'^0?(13|14|15|17|18|19)[0-9]{9}', '手机号有误')],
            error_messages={
                'max_length': '手机号不正确',
                'required': '邮箱不能为空'
            },
            widget=forms.widgets.TextInput(
                attrs={"class": "form-control"},
            )
        )
    
        # 重写全局的钩子函数,对确认密码做校验
        def clean(self):
            password = self.cleaned_data.get("password")
            rep_password = self.cleaned_data.get("rep_password")
    
            if rep_password and rep_password != password:
                self.add_error("rep_password", ValidationError("两次密码不一致"))
    
            else:
                return self.cleaned_data
    
        # 重写局部钩子函数,对手机号进行验证
        def clean_phone(self):
            phone = self.cleaned_data.get("phone")
            if models.UserInfo.objects.filter(phone=phone):
                raise ValidationError("手机号已被注册")
            else:
                return phone
    
        # 重写局部钩子函数,对用户名进行验证
        def clean_username(self):
            username = self.cleaned_data.get("username")
            if models.UserInfo.objects.filter(username=username):
                raise ValidationError("用户名已被注册")
            else:
                return username
    
        # 重写局部钩子函数,对邮箱进行验证
        def clean_email(self):
            email = self.cleaned_data.get("email")
            if models.UserInfo.objects.filter(email=email):
                raise ValidationError("邮箱已被注册")
            else:
                return email

    3、通过Ajax上传数据

    <script>
        $('#id_register').on('click', function () {
            //注册一个formData对象 利用它来提交表单、模拟表单提交,最大用法是可以上传二进制文件,把所有数据添加到formData对象就可以
            var formData = new FormData();
            // 把注册数据添加到formData对象
            formData.append('username', $('#id_username').val())
            formData.append('password', $('#id_password').val())
            formData.append('rep_password', $('#id_rep_password').val())
            formData.append('email', $('#id_email').val())
            formData.append('phone', $('#id_phone').val())
            //把头像文件添加到formData对象
            formData.append('avatar', $("#id_avatar")[0].files[0])
    
            $.ajax({
                url:'/register/',
                type:'post',
                processData: false,  // 告诉jQuery不要去处理发送的数据 传文件必须设置为false
                contentType: false,  // 告诉jQuery不要去设置Content-Type请求头 传文件必须设置为false
                data:formData,
                success:function (ret) {
                    if (ret.state == 1){
                        // 如果状态码为1,代表有错误,循环存有错误信息的对象,将错误信息添加到span标签,并给输入框加上has-error样式类
                        //each 循环函数
                        $.each(ret.msg, function (k,v) {
                            $('#id_'+k).next().text(v).parent().parent().addClass('has-error')
                        })
                    }else {
                        // 否则输入信息正确
                        alert('注册成功')
                        location.href='/login/'
                    }
                }
    
            })
        })
    
    
        // 将默认头像替换成用户选中的头像:值被修改事件
        $('#id_avatar').on('change', function () {
            //创建一个读取文件对象
            var fileReader = new FileReader()
            //取到当前选中的头像文件
            //console.log(this.files[0])
            //读取选中的头像文件 ,读取文件需要时间,需要等待读取完成才能加载到img标签中
            fileReader.readAsDataURL(this.files[0])
            //等待读取完毕后,将文件加载到img标签中
            fileReader.onload = function () {
                $('#id_img').attr('src',fileReader.result)
            }
        })
    
    </script>

    4、视图views处理

    def register(request):
        forms_obj = forms.Register()
        if request.method == 'POST':
            ret = {
                'state': 0,
                'msg': '',
            }
            forms_obj = forms.Register(request.POST)
            if forms_obj.is_valid():
                # 验证通过,将数据写入数据库
                forms_obj.cleaned_data.pop('rep_password')  # 删除重复密码 cleaned_data存放forms对象的数据
                avatar = request.FILES.get('avatar', None)  # 获取头像文件
                # print(avatar, type(avatar))
                # 将头像 密码等,写入数据库
                models.UserInfo.objects.create_user(avatar=avatar, **forms_obj.cleaned_data)
                return JsonResponse(ret)
            else:
                print(forms_obj.errors, type(forms_obj.errors))  # forms_obj.errors返回一个存有所有验证错误信息的对象
                ret = {
                    'state': 1,
                    'msg': forms_obj.errors
                }
                return JsonResponse(ret)
        return render(request, 'register.html', {'forms_obj': forms_obj})

    知识点:

      1、forms模块的使用,手机号字段自定义正则做校验,局部钩子与全局钩子做校验。

      2、Ajax上传文件的方式:利用FormData方法

      3、前端预览选中的文件方式:利用FileReader方法,需要注意读取文件需要时间,需要把文件读取完毕才进行显示

      4、后端接收文件及处理

    Ajax的参数:

      url:往哪请求

      type:请求方式

      dataType:json  接收的数据必须是json格式,接收后会自动反序列化,如果不是json数据,反序列化失败

      data:需要发送的数据

    更多参数:点击

      

     
  • 相关阅读:
    cnn softmax regression bp求导
    使用kd-tree加速k-means
    KDTree详解及java实现
    加入商品分类信息,考虑用户所处阶段的 图模型 推荐算法 Rws(random walk with stage)
    用户标签
    LDA(latent dirichlet allocation)
    对物品进行反馈 代码
    1.虚拟机中安装ubuntu
    4.动态HTML处理和机器图像识别
    3.非结构化数据与结构化数据提取
  • 原文地址:https://www.cnblogs.com/aizhinong/p/12301317.html
Copyright © 2011-2022 走看看