• 3- 功能2:基于forms组件和ajax实现注册功能


    1、forms组件的注册页面

     

    url

    from django.urls import path, re_path
    from blog import views
    from django.views.static import serve
    from cnblog import settings
    
    urlpatterns = [
        re_path('^login/$', views.login, name='login'),
        re_path('^get_validCode/$', views.get_validCode, name='get_validCode'),
        re_path('^index/$', views.index, name='index'),
        re_path('^register/$', views.register, name='register'),
    ]

    views视图

    from blog.myForms import UserForm  # froms组件
    
    
    def register(request):
        """
        注册页面
        :param request:
        :return:
        """
    
        form = UserForm
    
        return render(request, "blog/register.html", {'form':form})

    forms组件

    from django import forms
    from django.forms import widgets
    from blog.models import UserInfo
    from django.core.exceptions import ValidationError
    
    
    class UserForm(forms.Form):
        user = forms.CharField(max_length=32,label="用户名",
                               error_messages={"required": "该字段不能为空"},
                               widget=widgets.TextInput(attrs={"class": "form-control"}))
        pwd = forms.CharField(max_length=32, label="密码",
                              widget=widgets.PasswordInput(attrs={"class": "form-control"}))
        re_pwd = forms.CharField(max_length=32, label="确认密码",
                              widget=widgets.PasswordInput(attrs={"class": "form-control"}))
        email = forms.EmailField(max_length=32, label="邮箱",
                              widget=widgets.EmailInput(attrs={"class": "form-control"}))

    模板层

    <!DOCTYPE html>
    <html lang="en">
    <head>
        <meta charset="UTF-8">
        <title>Title</title>
        <link rel="stylesheet" href="/static/blog/bs/css/bootstrap.css">
        <script src="/static/js/jquery-3.2.1.min.js"></script>
    </head>
    <body>
    
    <h3>注册页面</h3>
    
    <div class="container">
        <div class="row">
            <div class="col-md-6 col-lg-offset-3">
                <form>
                    {% csrf_token %}
                    {% for field in form %}
                        <div class="form-group">
                            <label for="">{{ field.label }}</label>
                            {{ field }}
                        </div>
                    {% endfor %}
    
    
                    <div class="form-group">
                        <label for="">头像</label>
                        <img width="60" height="60" src="/static/img/default.jpg" alt="" id="avatar_img"
                             style="margin-left: 20px">
                        <input type="file" id="avatar">
                    </div>
    
                    <input type="button" class="btn btn-success register-btn" value="注册">
                </form>
            </div>
        </div>
    </div>
    </body>
    
    </html>
    View Code 

    2、头像上传,预览功能

     (1)label标签的for属性

       (2)头像图像,上传文件input框,一致

     

       (3)头像预览功能:获取input框的图片

     

    <!DOCTYPE html>
    <html lang="en">
    <head>
        <meta charset="UTF-8">
        <title>Title</title>
        <link rel="stylesheet" href="/static/blog/bs/css/bootstrap.css">
        <script src="/static/js/jquery-3.2.1.min.js"></script>
    </head>
    <body>
    
    <h3>注册页面</h3>
    
    <div class="container">
        <div class="row">
            <div class="col-md-6 col-lg-offset-3">
                <form>
                    {% csrf_token %}
                    {% for field in form %}
                        <div class="form-group">
                            <label for="{{ field.auto_id }}">{{ field.label }}</label>
                            {{ field }}
                        </div>
                    {% endfor %}
    
    
                    <div class="form-group">
                        <label for="avatar">头像
    
                            <img width="60" height="60" src="/static/img/default.jpg" alt="" id="avatar_img"
                                 style="margin-left: 20px">
                            <input type="file" id="avatar" style="display: none">
    
                        </label>
                    </div>
    
                    <input type="button" class="btn btn-success register-btn" value="注册">
                </form>
            </div>
        </div>
    </div>
    
    <script type="text/javascript">
        $(function () {
            $('#avatar').change(function () {
                //获取用户选中的文件对象
                var file_obj = $(this)[0].files[0];
    
                //获取文件对象的路径
                var reader = new FileReader();
                reader.readAsDataURL(file_obj);
    
                //修改img的src属性, src= 文件对象的路径
                // $(this).prepend('img').attr("src", reader.result);  // 等页面加载完成在执行onload
                reader.onload = function () {
                    $("#avatar_img").attr("src", reader.result)
                }
            })
        })
    </script>
    </body>
    
    </html>

    3、Ajax提交formdata数据

    (1)点击注册按钮

     

     

     注册视图

      (2)循环展示错误msg

      (3)代码优化:form表单数据序列化append

    4、forms组件的局部钩子,全局钩子

     

      

    5、注册成功,添加数据

    (1)模板层 跳转到view视图

      (2)view视图层

      (3)FieldFile字段

     

      数据库保存的是文件的路径
    

      

       (2)代码优化

     

     

    6、media配置

    Dajngo有两种静态文件:
    
         /static/    :  js,css,img
         /media/      :   用户上传文件
    

      

    settings配置

    # MEDIA配置:与用户上传相关的配置
    # 配置1:用户上传头像的文件
    MEDIA_ROOT = os.path.join(BASE_DIR, "media")
    
    
    # 配置2:开放media目录给用户
    MEDIA_URL = "/media/"

      

    配置1:settings配置media目录

        

     配置2:开放media目录给用户

    (3)开放给用户的目录

    开放给用户的目录
    http://127.0.0.1:8000/static/img/default.jpg
    http://127.0.0.1:8000/blog/media/avatars/mingren.jpg/    
    

    7、完整代码

    主url

    from django.contrib import admin
    from django.urls import path, re_path, include
    
    urlpatterns = [
        path('admin/', admin.site.urls),
        re_path(r'^blog/', include(('blog.urls', 'blog')))
    ]
    View Code

    url

    from django.urls import path, re_path
    from blog import views
    from django.views.static import serve
    from cnblog import settings
    
    urlpatterns = [
        re_path('^login/$', views.login, name='login'),
        re_path('^get_validCode/$', views.get_validCode, name='get_validCode'),
        re_path('^index/$', views.index, name='index'),
        re_path('^register/$', views.register, name='register'),
    
        # media配置
        re_path(r'^media/(?P<path>.*)/$', serve, {"document_root": settings.MEDIA_ROOT}),
    ]

    注册views视图

    from django.shortcuts import render, HttpResponse, redirect
    from blog.utils.validCode import get_validCode_img  # 导入验证码函数
    from django.http import JsonResponse  # Json数据返回到前端
    from django.contrib import auth     # 用户认证组件
    from blog.models import UserInfo
    from blog.myForms import UserForm  # froms组件
    
    
    def register(request):
        """
        注册页面
        :param request:
        :return:
        """
        # if request.method == 'POST':
        if request.is_ajax():
            response = {'user':None, "msg":None}
    
            form = UserForm(request.POST)
            if form.is_valid():
                response['user'] = form.cleaned_data.get("user")
    
                # 生成一条数据
                user = request.POST.get("user")
                pwd = request.POST.get("pwd")
                email = request.POST.get("email")
                avatar_obj = request.FILES.get("avatar")
                print(avatar_obj)
    
                extra_fields = {}
                if avatar_obj:
                    extra_fields["avatar"] = avatar_obj
    
                UserInfo.objects.create_user(username=user, password=pwd, email=email, **extra_fields)
    
                """
                if avatar_obj:
                    # 快捷键 alt + f7
                    UserInfo.objects.create_user(username=user, password=pwd, email=email, avatar=avatar_obj)
                else:
                    UserInfo.objects.create_user(username=user, password=pwd, email=email)
                """
    
            else:
                print(form.cleaned_data)
                print(form.errors)
                response['msg'] = form.errors
    
            return JsonResponse(response)
    
        form = UserForm
    
        return render(request, "blog/register.html", {'form':form})

    注册forms组件

    from django import forms
    from django.forms import widgets
    from blog.models import UserInfo
    from django.core.exceptions import ValidationError
    
    
    class UserForm(forms.Form):
        user = forms.CharField(max_length=32,label="用户名",
                               error_messages={"required": "该字段不能为空"},
                               widget=widgets.TextInput(attrs={"class": "form-control"}))
        pwd = forms.CharField(max_length=32, label="密码",
                              widget=widgets.PasswordInput(attrs={"class": "form-control"}))
        re_pwd = forms.CharField(max_length=32, label="确认密码",
                              widget=widgets.PasswordInput(attrs={"class": "form-control"}))
        email = forms.EmailField(max_length=32, label="邮箱",
                              widget=widgets.EmailInput(attrs={"class": "form-control"}))
    
        # 用户名的认证
        def clean_user(self):
            user = self.cleaned_data.get('user')
    
            user_obj = UserInfo.objects.filter(username=user).first()
            if not user_obj:
                return user
            else:
                raise ValidationError('该用户名已经注册')
                # return ValidationError('该用户名已经注册')   # 不能用出现bug
    
        # 密码
        def clean(self):
            pwd = self.cleaned_data.get("pwd")
            re_pwd = self.cleaned_data.get("re_pwd")
    
            if pwd and re_pwd:
                if pwd == re_pwd:
                    return self.cleaned_data
                else:
                    # return ValidationError("两次密码不一致!")
                    raise ValidationError("两次密码不一致!")
            else:
                return self.cleaned_data

    注册页面模板层

    <!DOCTYPE html>
    <html lang="en">
    <head>
        <meta charset="UTF-8">
        <title>Title</title>
        <link rel="stylesheet" href="/static/blog/bs/css/bootstrap.css">
        <script src="/static/js/jquery-3.2.1.min.js"></script>
    </head>
    <body>
    
    <h3>注册页面</h3>
    
    <div class="container">
        <div class="row">
            <div class="col-md-6 col-lg-offset-3">
                <form id="id_form">
                    {% csrf_token %}
                    {% for field in form %}
                        <div class="form-group">
                            <label for="{{ field.auto_id }}">{{ field.label }}</label>
                            {{ field }}
                            <span class="error pull-right" style="color: red"></span>
                        </div>
                    {% endfor %}
    
    
                    <div class="form-group">
                        <label for="avatar">头像
    
                            <img width="60" height="60" src="/static/img/default.jpg" alt="" id="avatar_img"
                                 style="margin-left: 20px">
                            <input type="file" id="avatar" style="display: none">
    
                        </label>
                    </div>
    
                    <input type="button" class="btn btn-success register-btn" value="注册">
                </form>
            </div>
        </div>
    </div>
    
    </body>
    
    </html>

    注册页面js代码

    <script type="text/javascript">
        $(function () {
            $('#avatar').change(function () {
                //获取用户选中的文件对象
                var file_obj = $(this)[0].files[0];
    
                //获取文件对象的路径
                var reader = new FileReader();
                reader.readAsDataURL(file_obj);
    
                //修改img的src属性, src= 文件对象的路径
                // $(this).prepend('img').attr("src", reader.result);  // 等页面加载完成在执行onload
                reader.onload = function () {
                    $("#avatar_img").attr("src", reader.result)
                }
            })
        });
    
        //基于ajax提交数据
        $(function () {
            $('.register-btn').click(function () {
    
                //获取数据
                var formdata = new FormData();
                <!--
                formdata.append("user", $('#id_user').val());
                formdata.append("pwd", $('#id_pwd').val());
                formdata.append("re_pwd", $('#id_re_pwd').val());
                formdata.append("email", $('#id_email').val());
                formdata.append("csrfmiddlewaretoken", $('[name="csrfmiddlewaretoken"]').val());
                -->
                var request_data = $('#id_form').serializeArray();
                $.each(request_data, function (index, data) {
                    formdata.append(data.name, data.value)
                });
    
                formdata.append("avatar", $("#avatar")[0].files[0]);
    
    
                $.ajax({
                    url: '',
                    type: 'post',
                    contentType: false,
                    processData: false,
                    data: formdata,
                    success: function (data) {
                        console.log(data);
                        if (data.user) { //注册成功
                            location.href = "/blog/login"
    
                        } else {
                            //清空错误信息,和div的样式
                            $('span.error').html("");
                            $(".form-group").removeClass("has-error");
    
                            //展示error_msg
                            $.each(data.msg, function (field, error_list) {
                                if (field == "__all__") {
                                    $('#id_re_pwd').next('span').html(error_list[0]).parent('div').addClass('has-error');
    
                                } else {
                                    $('#id_' + field).next('span').html(error_list[0]).parent('div').addClass('has-error');
    
                                }
                            })
    
                        }
    
                    }
                })
            })
        })
    
    </script>

    8、总结

    基于forms组件和Ajax实现注册功能
    
    
    # 1 基于forms组件设计注册页面
    
    
       ---点击头像===点击input
    
       ---头像预览:
          1 获取用户选中的文件对象
          2 获取文件对象的路径
          3 修改img的src属性 ,src=文件对象的路径
    
    # 2 错误信息:
       
       views:
    
           form.erorrs # {"user":[......]}
    
        Ajax.success:
           $.each(data.msg, function (field, error_list) {
                         
                            $("#id_" + field).next().html(error_list[0]);
                            $("#id_" + field).parent().addClass("has-error");
    
                        })
    
    # 3 局部钩子和全局钩子校验
       user字段不能重复
       两次密码不一致
    
    
    
    # 4 FileField与ImageFiled
    
      class UserInfo(AbstractUser):
          
          nid = models.AutoField(primary_key=True)
          telephone = models.CharField(max_length=11, null=True, unique=True)
          avatar = models.FileField(upload_to='avatars/', default="/avatars/default.png")
          
      avatar_obj=request.FILES.get("avatar")
      user_obj=UserInfo.objects.create_user(username=user,password=pwd,email=email,avatar=avatar_obj)
    
      Dajngo实现:
    
          会将文件对象下载到项目的根目录中avatars文件夹中(如果没有avatar文件夹,Django会自动创建),user_obj的avatar存的是文件的相对路径。
    
    
         
    # 5 Media 配置之MEDIA_ROOT:
    
    Dajngo有两种静态文件:
    
         /static/    :  js,css,img
         /media/      :   用户上传文件
    
    class UserInfo(AbstractUser):
          
          nid = models.AutoField(primary_key=True)
          telephone = models.CharField(max_length=11, null=True, unique=True)
          avatar = models.FileField(upload_to='avatars/', default="/avatars/default.png")
    
    
        avatar_obj=request.FILES.get("avatar")
      user_obj=UserInfo.objects.create_user(username=user,password=pwd,email=email,avatar=avatar_obj)
        
    
        一旦配置了
            MEDIA_ROOT=os.path.join(BASE_DIR,"media")
    
        Dajngo实现:
    
          会将文件对象下载到MEDIA_ROOT中avatars文件夹中(如果没有avatar文件夹,Django会自动创建),user_obj的avatar存的是文件的相对路径。
    
    
    # 6 Media 配置之MEDIA_URl:
    
       浏览器如何能直接访问到media中的数据
    
    
       settings.py:
          MEDIA_URL="/media/"
    
       urls.pt:
          # media配置:
          re_path(r"media/(?P<path>.*)$",serve,{"document_root":settings.MEDIA_ROOT})
  • 相关阅读:
    正则表达式验证手机和邮箱格式
    密码正则表达式
    正则表达式 ?<= 和 ?= 的用法
    无限极分类
    Linux下设置允许myql数据库远程连接
    一种高效的网络服务器设计
    多台计算机之间的ssh无密钥登录
    关于C语言指针的问题
    Windows下svn客户端和服务器的安装使用
    图解向hadoop分布式文件系统写文件的工作流程
  • 原文地址:https://www.cnblogs.com/venicid/p/9366977.html
Copyright © 2020-2023  润新知