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})

 

posted @ 2018-07-25 17:02  venicid  阅读(239)  评论(0编辑  收藏  举报