博客园项目

    

day 1 

  基于ajax,PIL实现随机图片验证码 以及geetest插件实现滑动验证码  的登录功能。

  1)生成随机验证码

  

  怎么实现呢?

  前端html代码

  贴上代码

<div class="row">
                       <div class="col-md-6">
                           <label for="id_valid">验证码</label>
                           <input type="text" class="form-control" id="id_valid" placeholder="验证码">
                       </div>
                       <div class="col-md-6">
                           <img src="/get_valid_code/" width="250px" height="50px" alt="">            //<img src='//'>src跟一个视图函数,走这个函数,拿到一个图片,会将页面重新渲染。
                       </div>
                   </div>

  点击实现刷新

  

<script>
    $('img').click(function () {
        console.log($(this));                    // console.log  r.fn.init [img]
        console.log($(this)[0]);                 // console.log  <img src=​"http:​/​/​127.0.0.1:​8000/​get_valid_code/​?" width=​"250px" height=​"50px" alt>​
        $(this)[0].src+='?'                      .src方法是DOM对象的方法  
    })
</script>

  视图函数

def get_valid_code(request):
    from PIL import Image,ImageDraw,ImageFont
    from io import BytesIO
    def get_color():
        return (random.randint(0,255),random.randint(0,255),random.randint(0,255))
    def get_char():
        random_num=str(random.randint(0,9))
        random_upper=chr(random.randint(65,90))
        random_lower=chr(random.randint(97,122))
        return random.choice([random_num,random_upper,random_lower])
    height=50
    width=250
    image=Image.new(mode='RGB',size=(width,height),color=get_color())
    print('image',image,type(image))                       #image <PIL.Image.Image image mode=RGB size=250x50 at 0x1E20FE94BA8> <class 'PIL.Image.Image'>
    draw=ImageDraw.Draw(image,mode='RGB')
    print('draw',draw,type(draw))                          #draw <PIL.ImageDraw.ImageDraw object at 0x000001E20FE94CF8> <class 'PIL.ImageDraw.ImageDraw'>
    font=ImageFont.truetype('app01/static/kumo.ttf',40)
    valid_code=''
    for i in range(6):
        char=get_char()
        valid_code+=char
        draw.text([i*40,5],char,get_color(),font=font)
    f=BytesIO()
    image.save(f,'png')
    data=f.getvalue()
    print('data',data,type(data))                          #data b'x89PNG...' <class 'bytes'>
   
   request.session["valid_code"]=valid_code               #将验证码放在session中

return HttpResponse(data)

   2)点击登录,触发ajax提交事件

   前端代码

    

 $('#id_login').click(function () {
        $.ajax({
            url:'/login/',
            type:'post',
            data:{username:$('#id_username').val(),
                password:$('#id_password').val(),
                csrfmiddlewaretoken:$("[name='csrfmiddlewaretoken']").val(),
                valid_code:$('#id_valid').val()
                },
            success:function (data) {
                if (data.status){
                    location.href='/index/'
                }
                else{
                    $('#id_login').next().text(data.error_msg);
                    setTimeout(function () {
                         $('#id_login').next().text('')
                    },1000)
                }
            }
        })
    })

  后端代码

def login(request):

    if request.is_ajax():
        username=request.POST.get('username')
        password=request.POST.get('password')
        valid_code=request.POST.get('valid_code')
        valid_CODE=request.session.get('valid_CODE')
        print(valid_CODE,valid_code)
        data={'status':None,'error_msg':None}
        if valid_code.lower()==valid_CODE.lower():
            user=auth.authenticate(username=username,password=password)        #验证有没有用户用auth.authenticate方法
            print(user)
            if user:
                data['status']=1
            else:
                data['status']=0
                data['error_msg']='用户名或密码不存在!'
        else:
            data['status']=0
            data['error_msg']='验证码不正确!'
        return JsonResponse(data)
    return render(request,'login.html')

day2 

  1 图像上传

  前端

  html代码

  PS label标签的妙用

    将<img>标签放在label标签内。这样在点击img标签的时候,就会触发label标签的事件,找到for='xx',在这里是找到<input type='file'>,会直接跳出其窗口。

                    <div class="form-group">
            <label for="id_avator" class="col-sm-2 control-label">头像<img style="margin-left: 80px" width="50px" height="50px" class="pull-left" id='id_img_avator' src="/static/default.png"></label> <div class="col-sm-10"> <input type="file" class="form-control" id="id_avator" placeholder="" style="display:None"> </div> </div>

  js代码

  PS   

    FileReader():读取文件,从文件中读取数据和保存在js变量中。

      参考知识网址:http://www.iunbug.com/archives/2012/06/04/220.html

  用FileReader():从文件中读取数据,存储到JS变量中

<script>
    $('#id_avator').change(function () {            //上传图片,change时间。
        var file=$(this)[0].files[0];
        var reader=new FileReader();
        reader.readAsDataURL(file);
        reader.onload=function () {
            console.log(this);                          //FileReader {readyState: 2, result: "data:image/jpeg;base64,/9j/4AAQSkZJRgABAQAAAQABAAD…oJDI5wRnHrmsm6kX3/OlSprsZj1Fwy/SevrSpUqeMLD//2Q==", error: null, onloadstart: null, onprogress: null, …}
            console.log(typeof this);                   //object
            $('#id_img_avator').attr('src',this.result)
        }
    })
</script>

  test:测试 file,reader,this.result到底是什么东西。

$('#id_avator').change(function () {
         var file=$(this)[0].files[0];
         console.log(file);
         console.log(typeof file);
         var reader=new FileReader();
         console.log(reader);
         console.log(typeof reader);
         reader.readAsDataURL(file);
         reader.onload=function () {
             console.log(this.result);
              $('#id_img_avator')[0].src=this.result}

     });

  输出:

File(17989) {name: "th.jpg", lastModified: 1513684937519, lastModifiedDate: Tue Dec 19 2017 20:02:17 GMT+0800 (中国标准时间), webkitRelativePath: "", size: 17989, …}
(index):116 object
(index):118 FileReader {readyState: 0, result: null, error: null, onloadstart: null, onprogress: null, …}
(index):119 object
(index):122 data:image/jpeg;base64,/9j/4AAQSkZJRgABAQAAAQABAAD/2wBDAAMCAgMCAgMDAwMEAwMEBQgFBQQEBQoHBwYIDAoMDAsKCwsNDhIQDQ4RDgsLEBYQERMUFRUVDA8...

  2 $.each()方法

  在js代码中

success:function (data) {
                if (data.user){
                    location.href='/index/'
                }
                else{
                    console.log(data.error_msg);
                    $('span').text('');
                    $('.form-control').removeClass('has-error');
                    $.each(data.error_msg,function (i,j) {                               
                        $('#id_'+i).next().addClass('pull-right').css('color','red').text(j[0]);
                        if (i=='__all__'){
                            $('#id_re_password').next().addClass('pull-right').css('color','red').html(j[0])
                        }
                    })
                }
            }

  data.error_msg是正宗的字典。

  function(i,j) i 会取到key值,j会取到value值。value值是一个列表。

  if i=='__all__',判断全局钩子,密码与确认密码是否一致。

  

  3 

$('#id_register').click(function () {
        var formdate=new FormData();
        formdate.append('username',$('#id_username').val());
        formdate.append('password',$('#id_password').val());
        formdate.append('re_password',$('#id_re_password').val());
        formdate.append('email',$('#id_email').val());
        formdate.append('valid_code',$('#id_valid_code').val());
        formdate.append('file_img',$('#id_avator')[0].files[0]);
        formdate.append("csrfmiddlewaretoken",$("[name='csrfmiddlewaretoken']").val());
        $.ajax({
            url:'/register/',
            type:'post',
            processData:false,
            contentType:false,
            data:formdate,

  

  $('#id_avator')[0].files[0]是一个DOM对象,文件内容。

  需要将它发送给后端,用到了FormData类。

  后端代码

  接收FormData,都在request.POST中。

  经过is_valid()方法处理完后,数据都在cleaned_data和errors中。

  文件是一个特殊的存在,它的发送和取出都与其他不一样。

def register(request):
    if request.is_ajax():
        formregister = FormRegister(request,request.POST)
        regResponse={'user':None,'error_msg':None}
        if formregister.is_valid():
            username=formregister.cleaned_data.get('username')
            password=formregister.cleaned_data.get('password')
            re_password=formregister.cleaned_data.get('re_password')
            email=formregister.cleaned_data.get('email')
            file_img=request.FILES.get('file_img')
            print('file_img',file_img,type(file_img))
            UserInfo.objects.create_user(username=username,password=password,email=email,avatar=file_img)
            regResponse['user']=1

  输出:

file_img th.jpg <class 'django.core.files.uploadedfile.InMemoryUploadedFile'>

  4 Form组件继承request

  forms.py 视为view.py 服务的

  在views.py中,视图函数

  def xxx(request):

    formreg=FormReg(request,request.POST):  

  在form.py中

  class FormReg(forms.Form)

    def__init__(request,*args,**kwargs)

      super().__init__(*args,**kwargs)

      self.request=request

    username=forms.Charfileld(..)

    ....

  这样 在form组件中,利用钩子可以去到保存在request.session中的验证码,可以在钩子里对验证码进行判定。

  解决了一个什么问题呢?

  form组件本身是单纯的帮助建立form表单的,除此之外好像并无别的高端用法。

  但form组件本质上是class类,类可以继承,在__init__的时候可以传参。

  so,form组件在views.py文件中实例化 的时候便可以传参,传各种需要的参数。

  将request传给form类,实例化的对象拿到request.session中的验证码。

  ajax提交,用户输入的验证码在request.POST中,经过is_valid(),在cleaned_data或者errors中。搞定!这样便可以验证了。

  高端的用法!

原文地址:https://www.cnblogs.com/654321cc/p/8066525.html