头像预览
$("#avatar_file").change(function(){ // 获取上传的文件对象 var file=$(this)[0].files[0]; // 读取文件的URL // 创建阅读器 var reader=new FileReader(); // 读取file的URL reader.readAsDataURL(file); // 监听读取,onload在读完之后触发事件(是给DOM对象绑定事件) reader.onload=function() { // this.result 是刚刚读取的结果 $("#avatar_img").attr("src",this.result) } });
头像预览
头像重叠于文件上传
css: /*头像与文件上传叠在一起,参照物是.avatar_box,已定位的父亲*/ #avatar_img{ width: 60px; height: 60px; left:; top:; } #avatar_file{ width: 60px; height: 60px; position: absolute; left:; top:; opacity:; } .avatar_box{ position: relative; }
头像与文件上传叠在一起
ajax注册+Form验证
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>Title</title> <link rel="stylesheet" href="/static/plugins/bootstrap/css/bootstrap.min.css"> <script src="/static/js/jquery-3.2.1.min.js"></script> <link rel="stylesheet" href="/static/css/register.css"> </head> <body> <div class="container"> <div class="row"> <div class="col-sm-6 col-sm-offset-3"> <form class="form-horizontal"> {% csrf_token %} <div class="form-group"> <label for="id_user" class="col-sm-2 control-label">用户名</label> <div class="col-sm-10"> {{ regForm.user }} <span class="pull-right"></span> </div> </div> <div class="form-group"> <label for="id_pwd" class="col-sm-2 control-label">密码</label> <div class="col-sm-10"> {{ regForm.pwd }}<span class="pull-right"></span> </div> </div> <div class="form-group"> <label for="id_repeat_pwd" class="col-sm-2 control-label">确认密码</label> <div class="col-sm-10"> {{ regForm.repeat_pwd }}<span class="pull-right"></span> </div> </div> <div class="form-group"> <label for="id_email" class="col-sm-2 control-label">邮箱</label> <div class="col-sm-10"> {{ regForm.email }}<span class="pull-right"></span> </div> </div> <div class="form-group"> <label for="avatar_file" class="col-sm-2 control-label">头像</label> <div class="col-sm-10"> <div class="avatar_box "> <img src="/static/img/default.png" alt="" id="avatar_img"> <input type="file" class="form-control" id="avatar_file"> </div> </div> </div> <div class="form-group"> <label for="id_valid_code" class="col-sm-2 control-label">验证码</label> <div class="col-sm-5"> {{ regForm.valid_code }}<span class="pull-right"></span> </div> <div class="col-sm-5"> <img style="margin-left: -17px" src="/get_valid_img/" alt="" width="230" height="33" id="valid_img"> </div> </div> <div class="form-group"> <div class="col-sm-offset-2 col-sm-10"> <input type="button" value="注册" class=" btn-primary form-control regBtn "> </div> </div> <div class="col-sm-offset-2 col-sm-10"> <div class="form-group" style="margin-left:-10px">已有账号?<a href="/login/">立即登录</a></div> </div> </form> </div> </div> </div> <script> // 刷新验证码 $("#valid_img").click(function () { $(this)[0].src += "?" }); // 头像预览 $("#avatar_file").change(function () { // 获取上传文件对象 var file = $(this)[0].files[0]; // 读取文件URL var reader = new FileReader(); reader.readAsDataURL(file); // 阅读文件完成后触发的事件 reader.onload = function () { $("#avatar_img").attr("src", this.result); // 读取的URL结果:this.result } }); // 提交注册数据 $(".regBtn").click(function () { var $formData = new FormData(); $formData.append("user", $("#id_user").val()); $formData.append("pwd", $("#id_pwd").val()); $formData.append("repeat_pwd", $("#id_repeat_pwd").val()); $formData.append("email", $("#id_email").val()); $formData.append("valid_code", $("#id_valid_code").val()); var file = $("#avatar_file")[0].files[0]; $formData.append("file_img", file); $formData.append("csrfmiddlewaretoken", $("[name='csrfmiddlewaretoken']").val()); $.ajax({ url: "/register/", type: "POST", data: $formData, processData: false, contentType: false, success: function (data) { if (data.user) { location.href = "/login/" } else { $("span").html(""); $(".form-group").removeClass("has-error"); console.log(data.errors); // {"user":["",""],"pwd":["",""]} $.each(data.errors, function (i, j) { // i : 错误字段名称 j: 该字段所有错误列表 $("#id_" + i).next().addClass("pull-right").css("color", "red").html(j[0]).parent().parent().addClass("has-error"); // __all__校验的是全局钩子 if (i == "__all__") { $("#id_repeat_pwd").next().addClass("pull-right").css("color", "red").html(j[0]).parent().parent().addClass("has-error"); } }) } } }) }) </script> </body> </html>
register.html
/*距顶端50px*/ .container { margin-top:100px; } body { background-color: #eeeeee; } /*头像与文件上传叠在一起,参照物是.avatar_box,已定位的父亲*/ #avatar_img { width: 60px; height: 60px; left:; top:; } #avatar_file { width: 60px; height: 60px; position: absolute; left:; top:; opacity:; } .avatar_box { position: relative; }
register.css
from django import forms from django.forms import widgets from .models import UserInfo from django.core.exceptions import NON_FIELD_ERRORS, ValidationError class RegForm(forms.Form): def __init__(self, request, *args, **kwargs): super().__init__(*args, **kwargs) self.request = request user = forms.CharField(min_length=5, max_length=12, error_messages={"min_length": "最小长度为5"}, widget=widgets.TextInput(attrs={"class": "form-control", "placeholder": "Username"}) ) pwd = forms.CharField( widget=widgets.PasswordInput(attrs={"class": "form-control", "placeholder": "Password"}) ) repeat_pwd = forms.CharField( widget=widgets.PasswordInput(attrs={"class": "form-control", "placeholder": "Confirm Password"}) ) email = forms.EmailField(error_messages={"invalid": "格式错误!"}, widget=widgets.EmailInput(attrs={"class": "form-control", "placeholder": "Email"}) ) valid_code = forms.CharField( widget=widgets.TextInput(attrs={"class": "form-control", "placeholder": "Validcode"}) ) def clean_user(self): user = UserInfo.objects.filter(username=self.cleaned_data.get("user")) if not user: return self.cleaned_data.get("user") else: raise ValidationError("用户名已经存在!") def clean_pwd(self): pwd = self.cleaned_data.get("pwd") if pwd.isdigit() or pwd.isalpha(): raise ValidationError("不能是纯数字或者纯字母") else: return pwd def clean_valid_code(self): val = self.cleaned_data.get("valid_code") # 用户输入的验证码 if val.upper() == self.request.session.get("valid_code_str").upper(): return self.cleaned_data.get("valid_code") else: raise ValidationError("valid code error!") def clean(self): if self.cleaned_data.get("pwd"): if self.cleaned_data.get("pwd") == self.cleaned_data.get("repeat_pwd"): return self.cleaned_data else: raise ValidationError("两次密码不一致!") # key 是__all__
forms.py
from django.shortcuts import render, redirect, HttpResponse import random from PIL import Image, ImageDraw, ImageFont from io import BytesIO from PIL import Image from django.contrib import auth from django.http import JsonResponse from .models import * def get_valid_img(request): def get_random_color(): # 生成随机色 return (random.randint(0, 255), random.randint(0, 255), random.randint(0, 255)) def get_random_char(): # 生成随机字符 random_num = str(random.randint(0, 9)) # 随机数字 random_upper_alph = chr(random.randint(65, 90)) # 随机大写字母 random_lowwer_alph = chr(random.randint(79, 122)) # 随机小写字母 random_char = random.choice([random_num, random_lowwer_alph, random_upper_alph]) return random_char # 返回随机字符 # 生成画布图片 image = Image.new(mode="RGB", size=(230, 33), color=get_random_color()) # 生成画笔 draw = ImageDraw.Draw(image, mode="RGB") # 指定字体 font = ImageFont.truetype("blog/static/font/kumo.ttf", 32) valid_code_str = "" # 用来拼接验证码 # 写入6个随机字符(数字,字母) for i in range(1, 6): char = get_random_char() valid_code_str += char # 拼接验证码 draw.text([i * 40, 5], char, get_random_color(), font=font) width = 230 height = 33 # 生成80个点 for i in range(80): draw.point((random.randint(0, width), random.randint(0, height)), fill=get_random_color()) # 生成两根干扰线 for i in range(2): x1 = random.randint(0, width) x2 = random.randint(0, width) y1 = random.randint(0, height) y2 = random.randint(0, height) draw.line((x1, y1, x2, y2), fill=get_random_color()) # 暂存内存 f = BytesIO() image.save(f, "png") # 从内存中取 data = f.getvalue() # 将验证码保存在session request.session["valid_code_str"] = valid_code_str return HttpResponse(data) def log_in(request): if request.is_ajax(): user = request.POST.get('username') pwd = request.POST.get('pwd') valid_code = request.POST.get('valid_code') # 获取session里面的验证码 valid_code_str = request.session.get("valid_code_str") # 也可以这样写:valid_code_str=request.session["valid_code_str"] loginResponse = {"user": None, "error_msg": ''} # 先对验证码进行校验(不区分大小写) if valid_code_str.upper() == valid_code.upper(): # 验证码通过,再对用户名密码进行校验(要导入auth) user = auth.authenticate(username=user, password=pwd) if user: auth.login(request, user) # 设置session loginResponse["user"] = user.username else: loginResponse["error_msg"] = "username or password is wrong!" else: # 验证码不通过,不再进行下面的验证,直接返回提示错误信息 loginResponse["error_msg"] = " valid code is wrong!" # JsonResponse可完成json数据的转换工作,简便! return JsonResponse(loginResponse) return render(request, 'login.html') def index(request): return render(request, 'index.html') from blog.forms import * from .forms import * def register(request): # ajax请求: if request.is_ajax(): regForm = RegForm(request, request.POST) regResponse = {"user": None, "errors": None} if regForm.is_valid(): # 注册 data = regForm.cleaned_data user = data.get("user") pwd = data.get("pwd") email = data.get("email") avatar_img = request.FILES.get("file_img") user_obj = UserInfo.objects.create_user(username=user, password=pwd, email=email, avatar=avatar_img) regResponse["user"] = user else: regResponse["errors"] = regForm.errors return JsonResponse(regResponse) # get请求: regForm = RegForm(request) return render(request, "register.html", {"regForm": regForm})
views.py
from django.conf.urls import url from django.contrib import admin from blog import views urlpatterns = [ url(r'^admin/', admin.site.urls), # 登录 url(r'^login/', views.log_in), # 验证码 url(r'^get_valid_img/', views.get_valid_img), # 注册 url(r'^register/', views.register), # 主页 url(r'^$', views.index), url(r'^index/', views.index), ]
urls.py
效果图:
错误提示: