• Django---Blog系统开发之注册页面(验证码&ajax发送文件)


     前端页面及渲染:

    静态文件的配置:setting.py:

      static 文件放在app下

    STATIC_URL = '/static/'
    
    STATIC_ROOT = (
        os.path.join(BASE_DIR,'blog01/static')
    )

    static目录结构:

    配置URL:

    from django.conf.urls import url,include
    from django.contrib import admin
    from blog01 import views
    
    urlpatterns = [
        url(r'^admin/', admin.site.urls),
        url(r'^blog/', include('blog01.urls')),
        url(r'^$',views.index),
        url(r'^index/',views.index),
        url(r'^register',views.register),
        url(r'login',views.log_in),
        url(r'valid_code',views.valid_code),
        url(r'logout',views.log_out),
        url(r'set_password',views.set_password),
    ]
    {% load staticfiles %}
    
    <!DOCTYPE html>
    <html lang="en">
    <head>
        <meta charset="UTF-8">
        <title>欢迎注册</title>
        <script src="{% static 'jquery-3.2.1.js' %}"></script>
        <link href="{% static 'bootstrap/css/bootstrap.css' %}" rel="stylesheet">
        <link href="{% static 'bootstrap/css/mystyle.css' %}" rel="stylesheet">
    
    </head>
    <body>
    <div class="container register_container">
        <div class="row">
            <div class="col-sm-5 col-sm-offset-1">
                <form>
                    {% csrf_token %} 
                    <div class="form-group">
                        <label for="username">请输入用户名</label>
                        <span class="user_error"></span>
                        {{ form_obj.username }}
    
                    </div>
    
                     <div class="form-group register_avatar">
                         <label for="avatar">请选择头像</label>
                         <img src="{% static  'imag/q.png' %}" class="register_avatar_img">
                         <input type="file" class="register_avatar_input" id="avatar" name="avatar">
    
    
                    </div>
    
                    <div class="form-group">
                        <label for="password">请输入密码</label>
                        <span class="password_error"></span>
                        {{ form_obj.password }}
    
                    </div>
    
                    <div class="form-group">
                        <label for="re_password">请再次输入密码</label>
                        <span class="re_password_error"></span>
                        {{ form_obj.re_password }}
    
                    </div>
    
                    <div class="form-group">
                        <label for="email">请输入邮箱</label>
                         <span class="email_error"></span>
                        {{ form_obj.email }}
    
                    </div>
    
                     <div class="form-group">
                         <label for="id_valid_code">验证码</label>
                         <span class="valid_code_error"></span>
                         <div class="row">
                             <div class="col-sm-6">
    
                                 {{ form_obj.valid_code }}
    
                             </div>
                             <div class="col-sm-6">
                                 <img src="/valid_code/" alt="" class="valid_img">
                                 <a class="img_refresh">刷新</a>
                             </div>
                         </div>
                    </div>
    
                    <button type="button" class="btn btn-default register_button">提交</button>
                </form>
            </div>
    
            <div class="col-sm-3 col-sm-offset-1">
                <img src="{% static 'imag/iamg_register.png' %}" alt="" >
            </div>
        </div>
    </div>
    
    
    <script src="{% static 'bootstrap/js/bootstrap.min.js' %}"></script>
    <script src="{% static 'bootstrap/js/myaction.js' %}"></script>
    </body>
    
    </html>
    register.html
    /*for register html*/
    
    .register_container{
        margin-top: 40px;
    }
    
    .re_password_error,.user_error,.email_error,.password_error,.re_password_error,.valid_code_error
    {color: red;
    margin-left: 50px}
    
    
    /*调input输入框和img标签的位置,保证两者完全重合*/
    .register_avatar{position: relative;
                     80px;
                    height: 80px}
    
    .register_avatar_img,.register_avatar_input{position: absolute;
                                            left: 80px;
                                            top: 0;
                                             80px;
                                            height: 80px}
    /*设置透明度,只显示图片。如果设置display=none的话,物理位置会消失,不能点击上传图片*/
    .register_avatar_input{opacity: 0}
    mystyle
    //失入焦点时判断密码是否一致
    $('#id_re_password').blur(function () {
        var pwd = $('#password').val();
        var re_pwd = $(this).val();
        if (pwd != re_pwd){
           var error_message = '密码不一致';
            $('.password_error_message').text(error_message)
        }
    });
    
    
    //得到焦点时清空错误提示信息
    $('#id_re_password').focus(function () {
        $('.password_error_message').text(' ')
    });
    
    //ajax 发送注册数据
    $('.register_button').click(function () {
    
        var formData = new FormData();
    
    
        var csrfmiddlewaretoken = $("[name='csrfmiddlewaretoken']").val();
        var username = $('#id_username').val();
        var password = $('#id_password').val();
        var re_password = $('#id_re_password').val();
        var email = $('#id_email').val();
        var valid_code = $('#id_valid_code').val();
        var avatar = $('#avatar')[0].files[0];
    
    
        formData.append("csrfmiddlewaretoken",csrfmiddlewaretoken);
        formData.append('username',username);
        formData.append('password',password);
        formData.append('re_password',re_password);
        formData.append('email',email);
        formData.append('valid_code', valid_code);
        formData.append('avatar',avatar);
    
        $.ajax({
                url:'/register/',
                type:'POST',
                data:formData,  //使用formadate,必须设置contentType,processDate为false
                contentType:false,
                processData:false,
                success:function (data) {
                    data = JSON.parse(data);
                    if (data['state']){
                        location.href = '/login/'
                    }
                    else {
    
                        $('.user_error').text(data['error_message']['username']);
                        $('.password_error').text(data['error_message']['password']);
                        $('.email_error').text(data['error_message']['email']);
                        $('.valid_code_error').text(data['error_message']['valid_code']);
                        if (data['error_message']['re_password']) {
                            $('.re_password_error').text(data['error_message']['re_password']);
                        }
                        else {
                            $('.re_password_error').text(data['error_message']['__all__']);
                        }
                    }
    
                }
            })
    });
    
    
    //头像预览
    
    $('.register_avatar_input').change(function () {
        var reader = new FileReader();
        var file = $('.register_avatar_input')[0].files[0];
        reader.readAsDataURL(file);
        reader.onload=function () {
            $('.register_avatar_img')[0].src = this.result;
            console.log($('.register_avatar_img')[0])
        }
    
    });
    
    
    
    
    //验证码刷新
    $('.img_refresh').click(function () {
        $('.valid_img')[0].src += '?';
    
    });
    my action
    from django.shortcuts import render,redirect,HttpResponse
    from django.contrib import auth
    from blog01.models import *
    from blog01 import models
    import random
    from io import BytesIO
    import json
    from blog01 import forms
    
    def valid_code(request):
        '''create valid code picture'''
        f = BytesIO() #实例化BytesIo,创建一个内存存储文件的句柄
        img = Image.new(mode='RGB', #图片格式
                        size=(120,30), #图片大小
                        color=(random.randint(0,255),random.randint(0,255),random.randint(0,255))) #随机设置图片颜色
        draw = ImageDraw.Draw(img,mode="RGB")  #创建画笔句柄,讲imag 传入进去
    
        code_list=[] #存储验证码
        for i in range(5):
            char = random.choice([chr(random.randint(65,90)),str(random.randint(0,9))]) #随机生成字母和数字
            code_list.append(char) #添加到存储验证码到列表
            font = ImageFont.truetype('blog01/static/bootstrap/fonts/kumo.ttf',28)  #设置字体和大小
            draw.text([i*24,0],char,(random.randint(0,255),random.randint(0,255),random.randint(0,255)),font=font)
    
        #画干扰线
        for i in range(5):
            x1 = random.randint(0, 120)
            y1 = random.randint(0, 120)
            x2 = random.randint(0, 120)
            y2 = random.randint(0, 120)
            draw.line((x1, y1, x2, y2), fill=(random.randint(0, 255),random.randint(10, 255),random.randint(64, 255)))
    
        # 画干扰点
        for i in range(40):
            draw.point([random.randint(0, 120), random.randint(0, 30)], fill=(random.randint(0, 255),random.randint(10, 255),random.randint(64, 255)))
    
        # 画干扰圆
        for i in range(40):
            draw.point([random.randint(0,120), random.randint(0, 30)], fill=(random.randint(0, 255),random.randint(10, 255),random.randint(64, 255)))
            x = random.randint(0, 120)
            y = random.randint(0, 30)
            draw.arc((x, y, x + 4, y + 4), 0, 90, fill=(random.randint(0, 255),random.randint(10, 255),random.randint(64, 255)))
    
        img.save(f,'png') #讲绘制好的图片保存到f内存里
        data = f.getvalue() #从f里获取存取的二进制文件
    
        validCode = ''.join(code_list)  #拼接验证码
    
        request.session['validCode']=validCode #讲验证码存入session里
    
        return HttpResponse(data) #讲二进制文件返回给前端
    
    
    
    
    def register(request):
        '''render register html'''
    
        form_obj = forms.RegisterForm()
        if request.method == "POST":
            reponse_data = {}
            state = False
            error_message = ''
            form_obj = forms.RegisterForm(request,request.POST)#
    
            if form_obj.is_valid(): #验证form 表单里的数据是否合格
                data = form_obj.cleaned_data  #clean_data取出jango form表单里的合格数据
                data.pop('re_password')  #删除非数据库里的字段
                data.pop('valid_code')
                file_obj = request.FILES.get("avatar")
                data['avatar'] = file_obj
                UserInfo.objects.create_user(**data) #userinfo继承django user,并创建用户(创建用户存数据时会自动给用户密码加密)
                state=True
    
            else:
                errors = form_obj.errors
                error_message = errors
            reponse_data['error_message']=error_message
            reponse_data['state']=state
            return HttpResponse(json.dumps(reponse_data)) #pythons数据类型和js数据类型不一样,记得json序列化一下
    
        return render(request,'register.html',{'form_obj':form_obj})
    views.py
    #!/usr/bin/env python
    # -*- coding: utf-8 -*-
    # Created by Mona on 2017/9/6
    
    from django import forms
    from django.core.exceptions import ValidationError
    from django.forms.utils import ErrorList
    from blog01 import models
    
    # ******************************register html*********************************************************
    class RegisterForm(forms.Form):
        '''create a Form class for register html'''
    
        def __init__(self, request=None,*args,**kwargs):
            super(RegisterForm,self).__init__(*args,**kwargs)
            self.request=request #要往session里加值,必须重写init方法,将request传入
    
    
        username = forms.CharField(min_length=5, #设置字段最小长度为5
                                   max_length=12,
                                   widget=forms.TextInput(attrs={'class':'form-control','placeholder':'Username'}),
                                   error_messages=({'required':'不能为空'})) #设置默认错误信息
    
        password = forms.CharField(widget=forms.PasswordInput(attrs={'class':'form-control','placeholder':'Password'}),
                                   error_messages={'required':'不能为空'})
        re_password = forms.CharField(widget=forms.PasswordInput(attrs={'class':'form-control','placeholder':'Password'}),
                                      error_messages={'required': '不能为空'})
        email = forms.EmailField(widget=forms.EmailInput(attrs={'class':'form-control','placeholder':'Email'}),
                                 error_messages={'required': '不能为空','invalid':'格式错误'})
    
        valid_code = forms.CharField(widget=forms.TextInput(attrs={'class':'form-control','placeholder':'Valid Code'}),
                                     error_messages={'required': '不能为空', 'invalid': '格式错误'})
    
        def clean_password(self):
            '''tail a hook for verification  设置局部的钩子对form表单定制验证方法,格式参照源码 '''
            if len(self.cleaned_data['password'])>=8:
    
                return self.cleaned_data['password']
            else:
                raise ValidationError('密码长度必须大于8位')
    
        def clean_re_password(self):
            '''tail a function for verification  '''
            if len(self.cleaned_data['re_password']) >= 8:
                return self.cleaned_data['re_password']
            else:
                raise ValidationError('密码长度必须大于8位')
    
        def clean_username(self):
            '''tail a function for username verification'''
            if self.cleaned_data['username'].isdigit() or self.cleaned_data['username'].isalpha():
                raise ValidationError('用户名必须由数字和字母组成')
            else:
                if models.UserInfo.objects.filter(username=self.cleaned_data['username']):
                    raise ValidationError('用户名已占用,请更改用户名')
                else:
                    return self.cleaned_data['username']
    
        def clean_valid_code(self):
            '''set global handler for valid code verification'''
            if self.cleaned_data.get('valid_code', '0').upper() == self.request.session['validCode'].upper():
                return self.cleaned_data['valid_code']
            else:
                raise ValidationError('验证码错误')
    
        def clean(self):
            '''set global hook for password verification. if first password equal repeat password,
            设置全局对钩子,对多个字段同时比较或验证'''
            if self.cleaned_data.get("password",0) == self.cleaned_data.get("re_password",1):
                return self.cleaned_data
            else:
                raise ValidationError("密码不一致")
    
    
    # ****************************************************************************************************
    form.py
  • 相关阅读:
    Kettle Spoon 数据源连接中报ORA12505, TNS:listener does not currently know of SID given in connect descriptor的错误
    oracle创建用户和删除用户sql
    Kettle Spoon表输入使用变量
    Kettle Spoon 资源库连接后新建转换打不开,报Invalid byte 1 of 1byte UTF8 sequence异常
    oracle 误删除表/表中数据,恢复方法
    让ie兼容css3新属性backroundsize
    网页设计中为啥少用奇数字体?
    浏览器差异总结,可以用此判断浏览器版本(转)
    ie浏览器f12下调“浏览器模式”和“文档模式”的区别
    jquery的淡入淡出和隐藏,展示函数在ie中应用的bug
  • 原文地址:https://www.cnblogs.com/mona524/p/7492193.html
Copyright © 2020-2023  润新知