我们实现登录功能的随机验证码的产生
views.py
def get_random_color(): return ( # 创建三个0-255的随机数 random.randint(0, 255), random.randint(0, 255), random.randint(0, 255) ) def login(request): if request.method == 'GET': return render(request, 'login.html') def get_valid_code(request): img = Image.new('RGB', (320, 35), color=get_random_color()) # 构建一个画布 img_draw = ImageDraw.Draw(img) # 将画布img应用到画板 font = ImageFont.truetype('static/font/ss.TTF', size=25) # 创建字体对象 random_code = '' # 将随机产生的数字保存为字符串 for i in range(5): # 每一次调用循环5次 char_num = random.randint(0, 9) # 从0到9之间产生一个数字 char_lower = chr(random.randint(97, 120)) # 产生小写字母 ascii码从97-120 char_upper = chr(random.randint(65, 90)) # 产生大写字符 ascii码从65-90 char_str = str(random.choice([char_num, char_lower, char_upper])) # 从产生的三个对象(数字,大写,小写字母)中挑选一个 # 将产生的随机对象通过img_draw.test放到img_draw中,第一个参数是范围 # ,第二个参数是对象,第三个参数是颜色,font是字体 img_draw.text((i * 30 + 20, 0), char_str, get_random_color(),font) random_code += char_str # 将产生的随机对象保存到random_code 中 width = 320 height = 35 for i in range(20): x1 = random.randint(0, width) x2 = random.randint(0, width) y1 = random.randint(0, height) y2 = random.randint(0, height) # 将产生的线写到img_draw中,第一个参数是在画布img中的坐标,第二个参数是线条填充的颜色 img_draw.line((x1, y1, x2, y2), fill=get_random_color()), for i in range(100): # 在画布img范围内随机产生点,第一个参数是坐标,第二个参数是点填充的颜色 img_draw.point([random.randint(0, width), random.randint(0, height)], fill=get_random_color()) x = random.randint(0, width) y = random.randint(0, height) # 通过img_draw.arc添加线条,第一个参数是线条的其实坐标,第二个参数是开始和结束,第三个参数是填充的颜色 img_draw.arc((x, y, x - 2, y + 3), 0, 9, fill=get_random_color()) print(random_code) request.session['valid_code'] = random_code # 将收集到的随机对象保存在session中 f = BytesIO() # 在内存中创建一个空文件 img.save(f, 'png') # 将完成的画布img保存在文件f中,文件格式为png data = f.getvalue() # 拿到文件f的内容,并将其赋值给data return HttpResponse(data) # 将返回给前端页面
前端的验证码代码
<div class="form-group"> <label for="">验证码</label> <div class="row"> <div class="col-md-6"> <input type="text" id="valid_code" class="form-control"> </div> <img width="300" height="35" src="/get_valid_code/" alt=""> </div> </div>
点击验证码改变
在前端页面
<script> $('#img_code').click(function () { //在路径后面加一个问号 $('#img_code')[0].src+='?' }) </script>
这样就能点击之后变换
实现登录
前端页面的方法
$('#btn').click(function () {
$.ajax({
url: '/login/',
type: 'post',
data: {
'name': $('#name').val(),
'pwd': $('#pwd').val(),
'valid_code': $('#valid_code').val(),
//属性选择器
'csrfmiddlewaretoken': $('[name="csrfmiddlewaretoken"]').val()
},
success: function (data) {
console.log(data)
if (data.user) {
location.href = '/index/'
} else {
$('#error').html(data.msg)
}
}
})
})
后台登录代码
def login(request): if request.method == 'GET': return render(request, 'login.html') # 判断前台是不是ajax请求 # elif request.is_ajax(): # name=request.POST.get('name') # pwd=request.POST.get('pwd') # valid_code=request.POST.get('valid_code') # if valid_code.upper==request.session.get('valid_code').upper(): # user=auth.authenticate(request,username=name,password=pwd) # if user: # pass # else: # # 用户名密码错误 elif request.is_ajax(): response={'user':None,'msg':None} name=request.POST.get('name') pwd=request.POST.get('pwd') valid_code=request.POST.get('valid_code') #判断传过来的验证码是否正确 # 从session中取出来 if valid_code.upper()==request.session['valid_code'].upper(): #该函数实现一个用户登录的功能。它本质上会在后端为该用户生成相关session数据。 user=auth.authenticate(request,username=name,password=pwd) if user: # ajax请求,不能返回render页面,或者redirect,之前给你返回字符串 auth.login(request,user) response['user']=name response['msg']=pwd else: # 用户名或密码错误 response['msg']='用户名或密码错误' else: response['msg']='验证码错误' return JsonResponse(response)
实现注册
views.py 中的register
def register(request): if request.method=='GET': my_form=myforms.RegForm() return render(request,'register.html',{'my_form':my_form}) elif request.is_ajax(): response={'status':100,'msg':None} print(request.POST) my_form = myforms.RegForm(request.POST) if my_form.is_valid(): # 存数据,返回正确信息 # 得用create_user,回忆一下为什么 # 定义一个字典,把清理的数据赋给它 dic=my_form.cleaned_data # 移除掉确认密码字段 dic.pop('re_password') # 取出上传的文件对象 my_file=request.FILES.get('my_file') # 如果上传的文件为空,这个字段不传,数据库里存默认值 if my_file: # 放到字典中 dic['avatar']=my_file # 存数据的时候,多肯定不行,少,可以能行(null=True),它是可以的 user=models.UserInfo.objects.create_user(**dic) ''' models.FileField 有了这个字段,存文件,以及往数据库放文件路径,统统不需要自己做了 只需要把文件对象赋给它就可以了 ''' # user=models.UserInfo.objects.create_user(username=name,password=pwd,avatar=文件对象) # 看看存没存进去 print(user.username) else: # 返回错误信息 response['status']=101 response['msg']=my_form.errors return JsonResponse(response)
register.html
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <link rel="stylesheet" href="/static/bootstrap-3.3.7-dist/css/bootstrap.min.css"> <script src="/static/jquery-3.3.1.js"></script> <title>注册</title> <style> {# 把文件空间隐藏#} #my_file{ display: none; } </style> {# <script>#} {# //等文档加载完毕之后,再进行操作#} {# window.onload = function () {#} {# //$("#id_name").val('lqz')#} {# }#} {##} {# </script>#} </head> <body> <div class="container-fluid"> <div class="row"> <div class="col-md-6 col-md-offset-3"> <h1>注册</h1> <form id="form"> {% csrf_token %} {% for foo in my_form %} <div class="form-group"> <label for="{{ foo.auto_id }}">{{ foo.label }}</label> {{ foo }} </div> {% endfor %} {# 加一个上传文件的控件#} <div class="form-group"> <label for="my_file">头像 <img src="/static/img/default.png" id="img_file" alt="" width="80" height="80" style="margin-left: 10px"> </label> <input type="file" id="my_file"> </div> <input type="button" value="注册" class="btn btn-primary " id="btn"><span class="error"></span> </form> </div> </div> </div> </body> <script> //这个控件值发生变化的事件 $("#my_file").change(function () { //alert(111) //先取出文件(图片) var file_obj = $("#my_file")[0].files[0]; //通过文件阅读器,把图片放到img标签上 //生成一个文件阅读器对象 var filereader = new FileReader() //把图片对象,读到filereader对象中 filereader.readAsDataURL(file_obj) //filereader.result 这是filereader对象的值 //把文件对象渲染到img标签上(这样不行.需要加载完成才能操作) {#$("#img_file").attr('src', filereader.result)#} {#alert(1)#} //等加载完成,在操作 filereader.onload=function () { $("#img_file").attr('src', filereader.result) } }) $("#btn").click(function () { //因为要上传文件,生成formdata对象 var formdata=new FormData() /*第一种方式 formdata.append('name',$("#id_name").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()) //把文件放到formdata中 formdata.append('my_file',$('#my_file')[0].files[0]) */ //$("#form").serializeArray()把form表单打包,转成对象(列表套字典) var arr=$("#form").serializeArray() //第二种方式 //jquery 的循环,传参数:第一个参数是要循环的对象,第二个参数是一个匿名函数 $.each(arr,function (key,obj) { //obj对应的是:{name: "name", value: "sfdae"} console.log(key) console.log(obj) formdata.append(obj.name,obj.value) }) //把文件放到formdata中 formdata.append('my_file',$('#my_file')[0].files[0]) console.log(arr) $.ajax({ url:'/register/', type:'post', //写什么来? processData:false, contentType:false, data:formdata, success:function (data) { console.log(data) } }) }) </script> {# <script>#} {# //等文档加载完毕之后,再进行操作#} {# $("#id_name").val('lqz')#} {# </script>#} </html>
form验证的myforms.py
from django import forms from django.forms import widgets from django.core.exceptions import ValidationError from blog import models class RegForm(forms.Form): username = forms.CharField(max_length=18, min_length=2, label='用户名', widget=widgets.TextInput(attrs={'class': 'form-control'}) ) password = forms.CharField(max_length=18, min_length=2, label='密码', widget=widgets.PasswordInput(attrs={'class': 'form-control'})) re_password = forms.CharField(max_length=18, min_length=2, label='确认密码', widget=widgets.PasswordInput(attrs={'class': 'form-control'})) email = forms.EmailField(label='邮箱', widget=widgets.TextInput(attrs={'class': 'form-control'})) # 局部校验钩子函数 def clean_username(self): name = self.cleaned_data.get('username') # 去数据库校验 ret = models.UserInfo.objects.filter(username=name).first() if ret: raise ValidationError('用户名已存在') return name # 全局校验钩子函数 def clean(self): pwd = self.cleaned_data.get('password') re_pwd = self.cleaned_data.get('re_password') if pwd and re_pwd: if pwd == re_pwd: return self.cleaned_data else: raise ValidationError('两次密码不一致')