Submit會直接提交表單數據,發送post請求css
Button只是一個普通按鈕html
2.當用戶認證組件中的字段不夠咱們使用時,能夠自定義其餘的字段前端
1 from django.contrib.auth.models import AbstractUser 2 class UserInfo(AbstractUser): 3 tel=models.CharField(max_length=32)
同時要配置settings文件:告訴Django哪一個app下的哪一個表jquery
AUTH_USER_MODEL="app01.UserInfo"ajax
此時原生的user表就變成了userinfo表django
圖片的處理要基於PIL模塊,下載PIL模塊,要下載包:pip3 install pillowjson
1 from django.contrib import admin 2 from django.urls import path 3 from app01 import views 4 urlpatterns = [ 5 path('admin/', admin.site.urls), 6 path('reg/', views.reg), 7 path('login/', views.login), 8 path('index/', views.index), 9 path('get_valid_img/', views.get_valid_img), 10 ]
1 from django.contrib.auth.models import AbstractUser 2 class UserInfo(AbstractUser): 3 email=models.CharField(max_length=32) 4 5 #向authform組件中的user表中增長其餘字段,字段增長後的表名叫app01_userinfo
1 class UserForm(forms.Form): 2 user=forms.CharField(min_length=5,label="用戶名") 3 pwd=forms.CharField(min_length=5,label="密碼") 4 r_pwd=forms.CharField(min_length=5,label='確認密碼') 5 email=forms.EmailField(min_length=5,label="郵箱")
1 def reg(request): 2 if request.method=="GET": 3 form=UserForm() 4 return render(request,"reg.html",locals()) 5 else: 6 form=UserForm(request.POST) 7 response_dic={"islogin":None} 8 if form.is_valid(): 9 user=request.POST.get("user") 10 pwd=request.POST.get("pwd") 11 email=request.POST.get("email") 12 UserInfo.objects.create_user(username=user,password=pwd,email=email) 13 response_dic["islogin"]=True 14 else: 15 response_dic["islogin"] = False 16 error=form.errors 17 response_dic["error"] = error 18 return HttpResponse(json.dumps(response_dic))
1 <!DOCTYPE html> 2 <html lang="en"> 3 <head> 4 <meta charset="UTF-8"> 5 <title>Title</title> 6 <link rel="stylesheet" href="/static/bootstrap-3.3.7-dist/css/bootstrap.css"> 7 </head> 8 <body> 9 <div class="container"> 10 <div class="row"> 11 <div class="col-md-8 col-md-offset-2"> 12 <h3>註冊頁面</h3> 13 <form action=""> 14 {% csrf_token %} 15 {% for field in form %} 16 <label for="">{{ field.label }}</label> 17 {{ field }} <p class="error"></p> 18 {% endfor %} 19 <input type="button" class="btn btn-success login_btn" value="提交"> 20 </form> 21 </div> 22 </div> 23 </div> 24 <script src="/static/js/jquery.js"></script> 25 <script> 26 $(".login_btn").click(function(){ 27 $.ajax({ 28 url:"", 29 type:"post", 30 data:{ 31 "user":$('#id_user').val(), 32 "pwd":$("#id_pwd").val(), 33 "r_pwd":$("#id_r_pwd").val(), 34 "email":$("#id_email").val(), 35 "csrfmiddlewaretoken":$("[name=csrfmiddlewaretoken]").val(), 36 }, 37 success:function(response){ 38 response.is_login==true 39 location.href="/login/" 40 } 41 }) 42 }) 43 </script> 44 </body> 45 </html>
1 def get_valid_img(request): 2 # 方式一:讀取指定的圖片 3 # with open("static/aaa.jpg","rb") as f: 4 # data=f.read() 5 6 # 方式二:基於PIL模塊,建立驗證碼圖片 7 # from PIL import Image 8 # 1.建立圖片 9 # img=Image.new("RGB",(350,34),"yellow") 10 # 原碼部分:三個參數分別是模式,圖片大小,背景色 11 # def new(mode, size, color=0): 12 # 顏色參數動態可使用三原色 13 # def get_do_color(): 14 # import random 15 # return (random.randint(0,255),random.randint(0,255),random.randint(0,255)) 16 # img=Image.new("RGB",(350,34),get_do_color()) 17 18 19 # 2.生成圖片 20 # f=open("valid.png","wb") 21 # img.save(f,"png") 22 # 原碼部分:fp是文件句柄 最後一個參數是文件格式,文件句柄就是文件存儲的位置 23 # def save(self, fp, format=None, **params): 24 # with open("valid.png","rb") as f: 25 # data=f.read() 26 # 每次都要放到磁盤中太浪費空間 27 28 # 方式三:將圖片存到內存中,對內存的控制須要io模塊 29 # from io import BytesIO 30 # from PIL import Image 31 # def get_do_color(): 32 # import random 33 # return (random.randint(0,255),random.randint(0,255),random.randint(0,255)) 34 # img=Image.new("RGB",(350,34),get_do_color()) 35 # f=BytesIO() 36 # 內存句柄,將文件存到內存中 37 # img.save(f,"png") 38 # data=f.getvalue() 39 # 從內存中讀取文件 40 41 42 # 方式四:完善文本 43 # from io import BytesIO 44 # from PIL import Image ,ImageFont,ImageDraw #爲圖片添加內容須要引入畫筆,ImageFont爲建立字體對象 45 # def get_do_color(): 46 # import random 47 # return (random.randint(0,255),random.randint(0,255),random.randint(0,255)) 48 # img=Image.new("RGB",(350,34),get_do_color()) 49 # draw=ImageDraw.Draw(img) #畫筆須要一個參數做爲畫板 50 # 構建字體對象 51 # font=ImageFont.truetype("static/font/kumo.ttf",40) 52 # draw.text((0,0),"aaaaaa",fill=get_do_color(),font=font) 53 # text方法原碼部分 54 # def text(self, xy, text, fill=None, font=None, anchor=None, *args, **kwargs): 55 # 畫筆的text方法 xy參數爲一個座標元組,表示畫在背景的哪裏,text爲須要畫的內容,fill是畫筆的顏色 56 # font表明字體 57 58 # 如下是圖片的生成,文本部分添加在上面 59 # f=BytesIO() 60 # img.save(f,"png") 61 # data=f.getvalue() 62 # return HttpResponse(data) 63 64 # 方式五 65 import random 66 from io import BytesIO 67 from PIL import Image, ImageFont, ImageDraw 68 def get_do_color(): 69 70 return (random.randint(0, 255), random.randint(0, 255), random.randint(0, 255)) 71 72 img = Image.new("RGB", (350, 34), get_do_color()) 73 draw = ImageDraw.Draw(img) 74 font = ImageFont.truetype("static/font/kumo.ttf", 40) 75 # 動態畫背景上的內容 76 77 content="" 78 for i in range(6): 79 random_num=str(random.randint(0,9)) 80 random_lower=chr(random.randint(97,122)) 81 random_upper=chr(random.randint(65,90)) 82 s=random.choice([random_num,random_lower,random_upper]) 83 i+=1 84 draw.text((20+i*40,0), s, fill=get_do_color(), font=font) 85 content=content+str(s) 86 del request.session["content"] 87 request.session["content"]=content 88 89 # 加噪點噪線,讓人能識別出來,機器識別不出來 90 width = 350 91 height = 34 92 for i in range(5): 93 x1 = random.randint(0, width) 94 x2 = random.randint(0, width) 95 y1 = random.randint(0, height) 96 y2 = random.randint(0, height) 97 draw.line((x1,y1,x2,y2),fill=get_do_color()) 98 for i in range(20): 99 draw.point([random.randint(0,width),random.randint(0,height)],fill=get_do_color()) 100 x=random.randint(0,width) 101 y=random.randint(0,height) 102 draw.arc((x,y,x+4,y+4),0,90,fill=get_do_color()) 103 104 f = BytesIO() 105 img.save(f, "png") 106 data = f.getvalue() 107 return HttpResponse(data)
1 def login(request): 2 if request.method=="GET": 3 return render(request,"login.html") 4 else: 5 user=request.POST.get("user") 6 pwd=request.POST.get("pwd") 7 yzm=request.POST.get("yzm") 8 response={"user":None,"error_msg":""} 9 if str(yzm).upper()==str(request.session.get("content")).upper(): 10 user_obj=auth.authenticate(username=user,password=pwd) 11 if user_obj: 12 response["user"]=user 13 else: 14 response["error_msg"] = "用戶名或密碼錯誤" 15 else: 16 response["error_msg"]="驗證碼錯誤" 17 return HttpResponse(json.dumps(response))
1 <!DOCTYPE html> 2 <html lang="en"> 3 <head> 4 <meta charset="UTF-8"> 5 <title>登陸</title> 6 <link rel="stylesheet" href="/static/bootstrap-3.3.7-dist/css/bootstrap.css"> 7 <script src="/static/js/jquery.js"></script> 8 </head> 9 <body style="background-image: url('https://ss0.bdstatic.com/k4oZeXSm1A5BphGlnYG/skin/831.jpg?2')"> 10 <div class="container" > 11 <dic class="row"> 12 <div class="col-md-offset-2 col-md-8"> 13 <form action=""> 14 {% csrf_token %} 15 <div class="form-group"> 16 <label for="">用戶名</label> 17 <input type="text" class="form-control" id="user"> 18 </div> 19 20 <div class="form-group"> 21 <label for="">密碼</label> 22 <input type="password" class="form-control" id="pwd"> 23 </div> 24 25 <div class="form-group"> 26 <label for="">驗證碼</label> 27 <div class="row"> 28 <div class="col-md-6 col-sm-6 col-lg-6"> 29 <input type="text" class="form-control" id="yzm"> 30 </div> 31 <div class="col-md-6 col-sm-6 col-lg-6"> 32 <img width="350" height="34" src="/get_valid_img/" alt=""> 33 </div> 34 </div> 35 </div> 36 <p class="error"></p> 37 <input type="button" value="提交" class="pull-right btn btn-success login_btn"> 38 </form> 39 </div> 40 </dic> 41 </div> 42 43 <script> 44 $(".login_btn").click(function(){ 45 $.ajax({ 46 url:"", 47 type:"post", 48 data:{ 49 "user":$("#user").val(), 50 "pwd":$("#pwd").val(), 51 "yzm":$("#yzm").val(), 52 "csrfmiddlewaretoken":$("[name=csrfmiddlewaretoken]").val() 53 }, 54 success:function(response){ 55 dic=JSON.parse(response); 56 if(dic.user){ 57 location.href="/index/"; 58 } 59 else{ 60 $(".error").val(dic.erroe_msg); 61 } 62 } 63 64 }) 65 }) 66 </script> 67 </body> 68 </html>
引入:from django.http import JsonResponsebootstrap
使用:return JsonResponse(dic)瀏覽器
做用:視圖函數中不用每一次向前端傳字典都Json了,前端經過ajax獲得的response不用parse了session
緣由:查看源碼
1 class JsonResponse(HttpResponse): 2 def __init__(self, data, encoder=DjangoJSONEncoder, safe=True, 3 json_dumps_params=None, **kwargs): 4 if safe and not isinstance(data, dict): 5 raise TypeError( 6 'In order to allow non-dict objects to be serialized set the ' 7 'safe parameter to False.' 8 ) 9 if json_dumps_params is None: 10 json_dumps_params = {} 11 kwargs.setdefault('content_type', 'application/json')
//原碼中修改了響應頭中的content_type,告訴瀏覽器以json的形式解碼
data = json.dumps(data, cls=encoder, **json_dumps_params)
//原碼中幫咱們作了序列化的工做
super().__init__(content=data, **kwargs)
//而且傳到了HttpResponse中
Ajax的success在接收到response時,會先看響應頭中有沒有 content_type,若是有,按照格式解碼,若是沒有,直接放到response中
Img標籤有一個獨特的刷新方式,在路徑(http://127.0.0.1:8000/get_valid_img/)後加問號就是獲取新的圖片,問號能夠不止一個,因此驗證碼的點擊刷新即爲img標籤綁定一個click事件
$("#img").click(function(){
$(this)[0].src+="?"
})
若是組件中的每個字段都有一樣的約束,能夠給該組件添加一個__init__ 方法,讓其在繼承父類__init__方法的同時,填加新的內容
def __init__(self,*args,**kwargs):
super().__init__(*args,**kwargs)
for filed in self.fields.values():
filed.widget.attrs.update({"class":"form-control"})
正常狀況下的全局鉤:會將全局錯誤放到__all__中
1 Def clean(self): 2 3 Pwd=seif.cleaned_data.get(「pwd」) 4 5 R_pwd=eif.cleaned_data(「r_pwd」) 6 7 If pew=r_pwd: 8 9 Return self.cleaned_data 10 11 Else: 12 13 Raise ValidationError(「兩次密碼不一致」) 14 15 讓全局錯誤放到其餘字段中: 16 17 Def clean(self): 18 19 Pwd=seif.cleaned_data.get(「pwd」) 20 21 R_pwd=eif.cleaned_data(「r_pwd」) 22 23 If pew=r_pwd: 24 25 Return self.cleaned_data 26 27 Else: 28 29 Self.add_error(「r_pwd」, ValidationError(「兩次密碼不一致」))