models.pyjavascript
from django.db import models from django.contrib.auth.models import AbstractUser class UserInfo(AbstractUser): """ 用戶信息 """ nid = models.AutoField(primary_key=True) telephone = models.CharField(max_length=11, null=True, unique=True) avatar = models.FileField(upload_to='avatars/', default='/avatars/default.png') create_time = models.DateTimeField(verbose_name='建立時間', auto_now_add=True) blog = models.OneToOneField(to='Blog', to_field='nid', null=True, on_delete=models.CASCADE) def __str__(self): return self.username class Blog(models.Model): """ 博客信息 """ nid = models.AutoField(primary_key=True) title = models.CharField(verbose_name='我的博客標題', max_length=64) site = models.CharField(verbose_name='我的博客後綴', max_length=32, unique=True) theme = models.CharField(verbose_name='博客主題', max_length=32) def __str__(self): return self.title class Category(models.Model): """ 博主我的文章分類表 """ nid = models.AutoField(primary_key=True) title = models.CharField(verbose_name='分類標題', max_length=32) blog = models.ForeignKey(verbose_name='所屬博客', to='Blog', to_field='nid', on_delete=models.CASCADE) def __str__(self): return self.title class Tag(models.Model): """ 博主我的文章標籤表 """ nid = models.AutoField(primary_key=True) title = models.CharField(verbose_name='標籤名稱', max_length=32) blog = models.ForeignKey(verbose_name='所屬博客', to='Blog', to_field='nid', on_delete=models.CASCADE) def __str__(self): return self.title class Article(models.Model): """ 文章信息 """ nid = models.AutoField(primary_key=True) title = models.CharField(max_length=50, verbose_name='文章標題') desc = models.CharField(max_length=255, verbose_name='文章描述') create_time = models.DateTimeField(verbose_name='建立時間') category = models.ForeignKey(to='Category', to_field='nid', null=True, on_delete=models.CASCADE) user = models.ForeignKey(verbose_name='做者', to='UserInfo', to_field='nid', on_delete=models.CASCADE) tags = models.ManyToManyField( to='Tag', through='Article2Tag', through_fields=('article','tag'), ) def __str__(self): return self.title class ArticleDetail(models.Model): """ 文章詳細表 """ nid = models.AutoField(primary_key=True) content = models.TextField() article = models.OneToOneField(to='Article', to_field='nid', on_delete=models.CASCADE) class Article2Tag(models.Model): """ 多對多,文章、標籤得第三張表 """ nid = models.AutoField(primary_key=True) article = models.ForeignKey(verbose_name='文章', to='Article', to_field='nid', on_delete=models.CASCADE) tag = models.ForeignKey(verbose_name='標籤', to='Tag', to_field='nid', on_delete=models.CASCADE) class Meta: unique_together = [ ('article', 'tag'), ] def __str__(self): v = self.article.title + '--' + self.tag.title return v class ArticleUpDown(models.Model): """ 點贊,踩滅表 """ nid = models.AutoField(primary_key=True) user = models.ForeignKey("UserInfo", null=True, on_delete=models.CASCADE) article = models.ForeignKey("Article", null=True, on_delete=models.CASCADE) is_up = models.BooleanField(default=True) class Meta: unique_together = [ ('article','user'), ] class Comment(models.Model): """ 評論表 """ nid = models.AutoField(primary_key=True) article = models.ForeignKey(verbose_name='評論文章', to='Article', to_field='nid', on_delete=models.CASCADE) user = models.ForeignKey(verbose_name='評論者', to='UserInfo', to_field='nid', on_delete=models.CASCADE) content = models.CharField(verbose_name='評論內容', max_length=255) create_time = models.DateTimeField(verbose_name='建立時間', auto_now_add=True) parent_comment = models.ForeignKey('self', null=True, on_delete=models.CASCADE) def __str__(self): return self.content
操做配置:css
AUTH_USER_MODEL = "blog.UserInfo" create database cnblog; DATABASES = { 'default': { 'ENGINE': 'django.db.backends.mysql', 'NAME': 'cnblog', 'USER': 'root', 'PASSWORD': '123', 'HOST': '127.0.0.1', 'PORT': 3306, } } import pymysql pymysql.install_as_MySQLdb() Tools/Run manage.py Task makemigrations migrate
。。。
結果:html
驗證碼得獲取:前端
方式一:java
<img width="260" height="35" src="/get_valid_img/" alt="">
def get_valid_img(request): # 方式一 with open('girl.jpg','rb') as f: data = f.read() return HttpResponse(data)
方式二:mysql
def get_valid_img(request): # 方式二 """ pip install pillow """ import PIL from PIL import Image import random def get_random_color(): return (random.randint(0,255),random.randint(0,255),random.randint(0,255)) image = Image.new('RGB',(260,35),get_random_color()) f = open('valid_code.png','wb') # 存在磁盤上 image.save(f,'png') f = open('valid_code.png','rb') data = f.read() f.close() return HttpResponse(data)
方式三:jquery
def get_valid_img(request): # 方式三 import PIL from PIL import Image import random def get_random_color(): return (random.randint(0,255),random.randint(0,255),random.randint(0,255)) image = Image.new('RGB',(260,35),get_random_color()) from io import BytesIO f = BytesIO() # 在內存中建立一張圖片 直接返回 image.save(f,'png') data = f.getvalue() return HttpResponse(data)
方式四:ajax
kumo.ttfsql
def get_valid_img(request): # 方式四 import PIL from PIL import Image,ImageDraw,ImageFont import random def get_random_color(): return (random.randint(0,255),random.randint(0,255),random.randint(0,255)) image = Image.new('RGB',(260,35),get_random_color()) draw = ImageDraw.Draw(image) font = ImageFont.truetype('app01/static/font/kumo.ttf',size=32) temp = [] # 生成5個隨機字符 for i in range(5): random_num = str(random.randint(0,9)) random_low_alpha = chr(random.randint(97,122)) random_upper_alpha = chr(random.randint(65,90)) random_char = random.choice([random_num,random_low_alpha,random_upper_alpha]) draw.text((24+i*36,0),random_char,get_random_color(),font=font) # 保存隨機數 temp.append(random_char) # 造點 造線 造圓 width = 210 height = 35 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()) for i in range(2): draw.point([random.randint(0,width),random.randint(0,height)],fill=get_random_color()) x = random.randint(0,width) y = random.randint(0,height) draw.arc((x,y,x+10,y+5),0,360,fill=get_random_color()) # 在內存中生成圖片 from io import BytesIO f = BytesIO() image.save(f,'png') data = f.getvalue() f.close() valid_str = ''.join(temp) print('valid_str:',valid_str) request.session['valid_str'] = valid_str return HttpResponse(data)
登陸驗證:django
<body> <h3>hello: {{ request.user.username }} , {{ request.user.email }}</h3> </body>
<input type="button" class="btn btn-default login-btn" value="提交"> <span class="error" style="color: red; margin-left: 10px;"></span>
<script src="/static/js/jquery-3.2.1.min.js"></script> <script type="text/javascript"> $('.login-btn').click(function () { $.ajax({ url:'', type:'post', data:{ csrfmiddlewaretoken:$("[name='csrfmiddlewaretoken']").val(), user:$('#user').val(), pwd:$('#pwd').val(), valid_code:$('#valid_code').val() }, success:function (data) { if(data.state){ location.href = '/index/' }else{ $('.error').text(data.msg) } } }) })
from django.shortcuts import render,HttpResponse,redirect from django.http import JsonResponse from django.contrib import auth def login(request): if request.is_ajax(): user = request.POST.get('user') pwd = request.POST.get('pwd') valid_code = request.POST.get('valid_code') valid_str = request.session.get('valid_str') res = {"state": False, "msg": None} if valid_code.upper() == valid_str.upper(): user = auth.authenticate(username = user,password = pwd) if user: res["state"] = True auth.login(request, user) else: res["msg"] = "username or pwd error" else: res["msg"] = "驗證碼錯誤" return JsonResponse(res) return render(request,'login.html') def index(request): if not request.user.username: return redirect('/login/') return render(request,'index.html')
驗證碼點擊刷新:
<img id="valid_img" width="260" height="35" src="/get_valid_img/" alt="">
//驗證碼點擊刷新 $('#valid_img').click(function () { $(this)[0].src += '?' })
示例:
from django.db import models from django.contrib.auth.models import AbstractUser class UserInfo(AbstractUser): """ 用戶信息 """ nid = models.AutoField(primary_key=True) telephone = models.CharField(max_length=11, null=True, unique=True) avatar = models.FileField(upload_to='avatars/', default='/avatars/default.png') create_time = models.DateTimeField(verbose_name='建立時間', auto_now_add=True) blog = models.OneToOneField(to='Blog', to_field='nid', null=True, on_delete=models.CASCADE) def __str__(self): return self.username class Blog(models.Model): """ 博客信息 """ nid = models.AutoField(primary_key=True) title = models.CharField(verbose_name='我的博客標題', max_length=64) site = models.CharField(verbose_name='我的博客後綴', max_length=32, unique=True) theme = models.CharField(verbose_name='博客主題', max_length=32) def __str__(self): return self.title class Category(models.Model): """ 博主我的文章分類表 """ nid = models.AutoField(primary_key=True) title = models.CharField(verbose_name='分類標題', max_length=32) blog = models.ForeignKey(verbose_name='所屬博客', to='Blog', to_field='nid', on_delete=models.CASCADE) def __str__(self): return self.title class Tag(models.Model): """ 博主我的文章標籤表 """ nid = models.AutoField(primary_key=True) title = models.CharField(verbose_name='標籤名稱', max_length=32) blog = models.ForeignKey(verbose_name='所屬博客', to='Blog', to_field='nid', on_delete=models.CASCADE) def __str__(self): return self.title class Article(models.Model): """ 文章信息 """ nid = models.AutoField(primary_key=True) title = models.CharField(max_length=50, verbose_name='文章標題') desc = models.CharField(max_length=255, verbose_name='文章描述') create_time = models.DateTimeField(verbose_name='建立時間') category = models.ForeignKey(to='Category', to_field='nid', null=True, on_delete=models.CASCADE) user = models.ForeignKey(verbose_name='做者', to='UserInfo', to_field='nid', on_delete=models.CASCADE) tags = models.ManyToManyField( to='Tag', through='Article2Tag', through_fields=('article','tag'), ) def __str__(self): return self.title class ArticleDetail(models.Model): """ 文章詳細表 """ nid = models.AutoField(primary_key=True) content = models.TextField() article = models.OneToOneField(to='Article', to_field='nid', on_delete=models.CASCADE) class Article2Tag(models.Model): """ 多對多,文章、標籤得第三張表 """ nid = models.AutoField(primary_key=True) article = models.ForeignKey(verbose_name='文章', to='Article', to_field='nid', on_delete=models.CASCADE) tag = models.ForeignKey(verbose_name='標籤', to='Tag', to_field='nid', on_delete=models.CASCADE) class Meta: unique_together = [ ('article', 'tag'), ] def __str__(self): v = self.article.title + '--' + self.tag.title return v class ArticleUpDown(models.Model): """ 點贊,踩滅表 """ nid = models.AutoField(primary_key=True) user = models.ForeignKey("UserInfo", null=True, on_delete=models.CASCADE) article = models.ForeignKey("Article", null=True, on_delete=models.CASCADE) is_up = models.BooleanField(default=True) class Meta: unique_together = [ ('article','user'), ] class Comment(models.Model): """ 評論表 """ nid = models.AutoField(primary_key=True) article = models.ForeignKey(verbose_name='評論文章', to='Article', to_field='nid', on_delete=models.CASCADE) user = models.ForeignKey(verbose_name='評論者', to='UserInfo', to_field='nid', on_delete=models.CASCADE) content = models.CharField(verbose_name='評論內容', max_length=255) create_time = models.DateTimeField(verbose_name='建立時間', auto_now_add=True) parent_comment = models.ForeignKey('self', null=True, on_delete=models.CASCADE) def __str__(self): return self.content
from django.shortcuts import render,HttpResponse,redirect from django.http import JsonResponse from django.contrib import auth def login(request): if request.is_ajax(): user = request.POST.get('user') pwd = request.POST.get('pwd') valid_code = request.POST.get('valid_code') valid_str = request.session.get('valid_str') res = {"state": False, "msg": None} if valid_code.upper() == valid_str.upper(): user = auth.authenticate(username = user,password = pwd) if user: res["state"] = True auth.login(request, user) else: res["msg"] = "username or pwd error" else: res["msg"] = "驗證碼錯誤" return JsonResponse(res) return render(request,'login.html') def index(request): if not request.user.username: return redirect('/login/') return render(request,'index.html') def get_valid_img(request): # 方式四 import PIL from PIL import Image,ImageDraw,ImageFont import random def get_random_color(): return (random.randint(0,255),random.randint(0,255),random.randint(0,255)) image = Image.new('RGB',(260,35),get_random_color()) draw = ImageDraw.Draw(image) font = ImageFont.truetype('app01/static/font/kumo.ttf',size=32) temp = [] # 生成5個隨機字符 for i in range(5): random_num = str(random.randint(0,9)) random_low_alpha = chr(random.randint(97,122)) random_upper_alpha = chr(random.randint(65,90)) random_char = random.choice([random_num,random_low_alpha,random_upper_alpha]) draw.text((24+i*36,0),random_char,get_random_color(),font=font) # 保存隨機數 temp.append(random_char) # 造點 造線 造圓 width = 210 height = 35 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()) for i in range(2): draw.point([random.randint(0,width),random.randint(0,height)],fill=get_random_color()) x = random.randint(0,width) y = random.randint(0,height) draw.arc((x,y,x+10,y+5),0,360,fill=get_random_color()) # 在內存中生成圖片 from io import BytesIO f = BytesIO() image.save(f,'png') data = f.getvalue() f.close() valid_str = ''.join(temp) print('valid_str:',valid_str) request.session['valid_str'] = valid_str return HttpResponse(data) # 方式三 # import PIL # from PIL import Image # # import random # # def get_random_color(): # return (random.randint(0,255),random.randint(0,255),random.randint(0,255)) # # image = Image.new('RGB',(260,35),get_random_color()) # # from io import BytesIO # f = BytesIO() # 在內存中建立一張圖片 直接返回 # image.save(f,'png') # # data = f.getvalue() # # return HttpResponse(data) # 方式二 # """ # pip install pillow # """ # import PIL # from PIL import Image # # import random # # def get_random_color(): # return (random.randint(0,255),random.randint(0,255),random.randint(0,255)) # # image = Image.new('RGB',(260,35),get_random_color()) # # f = open('valid_code.png','wb') # 存在磁盤上 # image.save(f,'png') # # f = open('valid_code.png','rb') # data = f.read() # f.close() # # return HttpResponse(data) # 方式一 # with open('girl.jpg','rb') as f: # data = f.read() # # return HttpResponse(data)
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>index</title> </head> <body> <h3>hello: {{ request.user.username }} , {{ request.user.email }}</h3> </body> </html>
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>login</title> <link rel="stylesheet" href="/static/bootstrap-3.3.7/css/bootstrap.css"> <style type="text/css"> .container{ margin-top: 100px;} </style> </head> <body> <div class="container"> <div class="row"> <div class="col-md-6 col-md-offset-3"> <form> {% csrf_token %} <div class="form-group"> <label for="user">用戶名</label> <input type="text" class="form-control" id="user" placeholder="Username"> </div> <div class="form-group"> <label for="pwd">密碼</label> <input type="password" class="form-control" id="pwd" placeholder="Password"> </div> <div class="form-group"> <label for="pwd">驗證碼</label> <div class="row"> <div class="col-md-6"> <input type="text" class="form-control" id="valid_code"> </div> <div class="col-md-6"> <img id="valid_img" width="260" height="35" src="/get_valid_img/" alt=""> </div> </div> </div> <input type="button" class="btn btn-default login-btn" value="提交"> <span class="error" style="color: red; margin-left: 10px;"></span> </form> </div> </div> </div> <script src="/static/js/jquery-3.2.1.min.js"></script> <script type="text/javascript"> //提交 $('.login-btn').click(function () { $.ajax({ url:'', type:'post', data:{ csrfmiddlewaretoken:$("[name='csrfmiddlewaretoken']").val(), user:$('#user').val(), pwd:$('#pwd').val(), valid_code:$('#valid_code').val() }, success:function (data) { if(data.state){ location.href = '/index/' }else{ $('.error').text(data.msg) } } }) }); //驗證碼點擊刷新 $('#valid_img').click(function () { $(this)[0].src += '?' }) </script> </body> </html>
注:
css js 靜態文件
css js 存在靜態文件中 修改以後,client(瀏覽器)若是沒有修改;
需設置一些 瀏覽器得setting Disable cache
django-ajax http://www.cnblogs.com/yuanchenqi/articles/7638956.html
基於form表單提交數據:
默認值:Content—Type = urlencoded
<form action="" method="post" enctype="application/x-www-form-urlencoded">
print(request.POST)
<QueryDict: {'csrfmiddlewaretoken': ['azZWQlmRhdPPXxtRf9e04B31VZLyVJN8Dc1eAuWEMIxnWShqNP5IyxbozXVRjx8A'],
'user': ['alex'],
'avatar': ['girl.jpg']}> # 其實文件並無傳上來,只是個名稱!
print(request.FILES)
<MultiValueDict: {}>
涉及到上傳文件時:Content—Type = form-data
<form action="" method="post" enctype="multipart/form-data">
print(request.POST)
<QueryDict: {'csrfmiddlewaretoken': ['gsAIE42u5Io47YttQO9ExBEFuZiVZ965J5C0odChAd6C6jh2ou0m1xM28XsenXrx'],
'user': ['alex']}>
print(request.FILES)
<MultiValueDict: {'avatar': [<InMemoryUploadedFile: girl.jpg (image/jpeg)>]}>
基於Ajax提交數據:
$('#btn').click(function () {
$.ajax({
url:'',
type:'get',
data:{name:'alex',pwd:'123'},
success:function (data) {
console.log(data)
}
})
})
涉及到上傳文件時:
<script src="http://cdn.static.runoob.com/libs/jquery/1.10.2/jquery.min.js"></script>
<script type="text/javascript">
$('#btn').click(function () {
formdate = new FormData(); // 加var 局部, 不加var就是 全局.
formdate.append("user",$('#user').val());
formdate.append("avatar",$('#avatar')[0].files[0]);
formdate.append("csrfmiddlewaretoken",$('input[name="csrfmiddlewaretoken"]').val());
$.ajax({
url:'',
type:'post',
data:formdate,
contentType:false,
processData:false,
success:function (data) {
console.log(data)
}
})
})
</script>
<QueryDict: {'user': ['alice'], 'csrfmiddlewaretoken': ['9ipnZT2GROgz1BFiCZzsYTE32MCBPXKWCVrFJ2CtmjY70WtRaFqasPMqGKMUdL5o']}>
<MultiValueDict: {'avatar': [<InMemoryUploadedFile: girl.jpg (image/jpeg)>]}>
def upload(request): if request.method == 'POST': print(request.POST) print(request.FILES) obj = request.FILES.get('avatar') with open(obj.name,'wb') as f: for line in obj: f.write(line) return HttpResponse('OK') return render(request,'upload.html')
upload.html
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>Title</title> </head> <body> <h3>基於form表單提交數據</h3> {#<form action="" method="post" enctype="application/x-www-form-urlencoded">#} <form action="" method="post" enctype="multipart/form-data"> {% csrf_token %} <p>用戶名 <input type="text" name="user"></p> <p>頭像 <input type="file" name="avatar"></p> <input type="submit"> </form> <hr> <h3>基於Ajax提交文件數據</h3> <form> {% csrf_token %} <p>用戶名 <input type="text" id="user"></p> <p>頭像 <input type="file" id="avatar"></p> <input type="button" value="submit" id="btn"> </form> <script src="http://cdn.static.runoob.com/libs/jquery/1.10.2/jquery.min.js"></script> <script type="text/javascript"> $('#btn').click(function () { formdate = new FormData(); // 加var 局部, 不加var就是 全局. formdate.append("user",$('#user').val()); formdate.append("avatar",$('#avatar')[0].files[0]); formdate.append("csrfmiddlewaretoken",$('input[name="csrfmiddlewaretoken"]').val()); $.ajax({ url:'', type:'post', data:formdate, contentType:false, processData:false, success:function (data) { console.log(data) } }) }) </script> </body> </html>
頭像默認圖片
#avatar{ display: none} .avatar{ width: 60px; height: 60px;margin-left: 15px;cursor: pointer;}
<div class="form-group"> <label for="avatar">頭像 <img class="avatar" src="/static/img/default.png" alt=""> </label> <input type="file" id="avatar"> </div>
圖像預覽
//圖像預覽 $('#avatar').change(function () { var choose_file = $(this)[0].files[0]; //文件對象 var reader = new FileReader(); // 閱讀器對象 reader.readAsDataURL(choose_file); reader.onload = function (ev) { $('.avatar').attr('src',reader.result) }; {#$('.avatar').attr('src',reader.result) // 還沒讀完,就執行了這句了 出問題了!!#} //解決辦法 reader.onload });
注意:
爲何 src="/static/img/default.png" 可訪問到 ?
由於: settings 配置了 STATIC_URL = '/static/'
STATIC_URL = '/static/'
/static/... 對外得文件能夠直接訪問
Ajax 註冊:
from django import forms from django.forms import widgets,ValidationError from app01.models import UserInfo class RegForm(forms.Form): user = forms.CharField(max_length=8,label='用戶名', widget=widgets.TextInput(attrs={'class':'form-control'})) pwd = forms.CharField(min_length=4,label='密碼', widget=widgets.PasswordInput(attrs={'class':'form-control'})) repeat_pwd = forms.CharField(min_length=4,label='確認密碼', widget=widgets.PasswordInput(attrs={'class': 'form-control'})) email = forms.EmailField(label='郵箱', widget=widgets.EmailInput(attrs={'class': 'form-control'})) # 局部鉤子 def clean_user(self): val = self.cleaned_data.get('user') ret = UserInfo.objects.filter(username = val) if not ret: return val else: raise ValidationError('該用戶已存在') # 校驗局部鉤子得時候 沒有辦法 拿到 全部得乾淨數據, # 如何 校驗 兩個 字段呢! 全局鉤子 # 全局鉤子 能獲得 任何一個乾淨得 數據 def clean(self):return self.cleaned_data def clean(self): if self.cleaned_data.get('pwd') == self.cleaned_data.get('repeat_pwd'): return self.cleaned_data else: raise ValidationError('兩次密碼不一致') from django.http import JsonResponse def reg(request): if request.method == 'POST': res = {'user':None,'error_dict':None} form = RegForm(request.POST) if form.is_valid(): print("clean:",form.cleaned_data) # {"user":'yuan','pwd':"123"} print(request.FILES) user = form.cleaned_data.get('user') pwd = form.cleaned_data.get('pwd') email = form.cleaned_data.get('email') avatar = request.FILES.get('avatar') if avatar: # 接受文件對象 將avatar文件對象下載到avatar字段對應的upload_to指定路徑 沒指定在 根目錄下 user = UserInfo.objects.create_user(username=user,password=pwd,email=email,avatar=avatar) else: user = UserInfo.objects.create_user(username=user, password=pwd, email=email) res['user'] = user.username else: print('error:',form.errors) #{"repear_pwd":['',''],"email":['',''],} res['error_dict'] = form.errors return JsonResponse(res) form = RegForm() return render(request,'reg.html',locals())
// 註冊事件 $('.reg_btn').click(function () { 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("avatar",$('#avatar')[0].files[0]); formdata.append("csrfmiddlewaretoken",$('input[name="csrfmiddlewaretoken"]').val()); $.ajax({ url:'', type:'post', contentType:false, processData:false, data:formdata, success:function (data) { if(data.user){ //註冊成功 location.href = "/login/" }else{ //註冊失敗 //清空錯誤信息 $('form span').html(""); $('form .form-group').removeClass('has-error'); // 加載錯誤信息 $.each(data.error_dict,function (field,error_list) { // 全局 if(field == "__all__"){ $('#id_repeat_pwd').next().text(error_list[0]).css('color','red'); $('#id_repeat_pwd').parent().addClass('has-error') } $('#id_'+field).next().text(error_list[0]).css('color','red'); $('#id_'+field).parent().addClass('has-error') }) } } }) })
注意點:
1. 局部鉤子 與 全局鉤子:
def clean_user(self): pass 局部鉤子 只能校驗某一個字段
def clean(self): pass 能夠校驗兩個不一樣得字段,全局鉤子,能獲得任何一個乾淨得數據!!
局部鉤子得源碼:
try: if isinstance(field, FileField): initial = self.get_initial_for_field(field, name) value = field.clean(value, initial) else: value = field.clean(value) self.cleaned_data[name] = value if hasattr(self, 'clean_%s' % name): value = getattr(self, 'clean_%s' % name)() self.cleaned_data[name] = value except ValidationError as e: self.add_error(name, e)
全局鉤子得源碼:
try: cleaned_data = self.clean() except ValidationError as e: self.add_error(None, e) else: if cleaned_data is not None: self.cleaned_data = cleaned_data
2. 上傳文件:
formdata = new FormData();
formdata.append("avatar",$('#avatar')[0].files[0]); # 文件對象 formdata.append("csrfmiddlewaretoken",$('input[name="csrfmiddlewaretoken"]').val());contentType:false, processData:false, data:formdata,
。。。
3. ajax得局部刷新:
註冊失敗:
1. 清空錯誤信息
$('form span').html("");
$('form .form-group').removeClass('has-error');
2. 加載錯誤信息 each$.each(data.error_dict,function (field,error_list) { // 全局 全局得錯誤信息 field == '__all__' if(field == "__all__"){ $('#id_repeat_pwd').next().text(error_list[0]).css('color','red'); $('#id_repeat_pwd').parent().addClass('has-error') } $('#id_'+field).next().text(error_list[0]).css('color','red'); $('#id_'+field).parent().addClass('has-error') })
4.上傳文件 得存放地址:media 配置
avatar = models.FileField(upload_to='avatars/', default='avatars/default.png')FileField ImgField 傳什麼數據呢? 文件對象
前端:
formdata.append("avatar",$('#avatar')[0].files[0]); # 文件對象
後臺:
avatar = request.FILES.get('avatar') # 文件對象
if avatar:
# 接收文件對象 將avatar文件對象下載到avatar字段對應的upload_to(upload_to='avatars/')指定路徑下
user = UserInfo.objects.create_user(username=user,password=pwd,email=email,avatar=avatar)
else:
user = UserInfo.objects.create_user(username=user, password=pwd, email=email)
真實文件:
upload_to='' 存在項目得根目錄下 girl.jpg
upload_to='avatars/' 存在項目得根目錄下 /avatars/girl.jpg 注意: 相對路徑 不是絕對路徑,若是upload_to='/avatars/'會報錯!!
userinfo:
庫裏存得是 相對路徑!! avatars/girl.jpg
BUT:
用戶我的得文件 不該該存在項目得根目錄下: ??
知識點:
靜態文件 /static/css..js..img.. 用戶可直接 url 訪問獲得
由於:settings 配置 STATIC_URL = '/static/'
用戶文件:存用戶得我的信息 頭像 簡歷。。。 存在哪裏呢???
media 配置 存用戶信息 針對用戶上傳得文件
avatar = models.FileField(upload_to='avatars/', default='avatars/default.png')
settings
1.MEDIA_ROOT = os.path.join(BASE_DIR,'app01','media') # 針對 upload_to 得相對位置得!!
2.MEDIA_URL = '/media/' # 針對 用戶經過 url 訪問得!!
3.urls.py
from django.views.static import serve
from bbs import settings
re_path(r'media/(?P<path>.*)$',serve,{'document_root':settings.MEDIA_ROOT}) # 針對 用戶經過 url 訪問得!!
media 配置以後:
用戶可直接訪問相似於訪問/static/img/...
upload_to='avatars/' 用戶上傳得文件就會存在 /media/avatars/girl.jpg 庫裏存得是,相對路徑! avatars/girl.jpg
注意:
# avatar = models.FileField(upload_to='avatars/', default='avatars/default.png')
# 若是用戶沒有上傳圖片,使用默認得!!avatar 不須要傳!!
avatar = request.FILES.get('avatar')
if avatar:
user = UserInfo.objects.create_user(username=user,password=pwd,email=email,avatar=avatar)
else:
user = UserInfo.objects.create_user(username=user, password=pwd, email=email)
示例:
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>reg</title> <link rel="stylesheet" href="/static/bootstrap-3.3.7/css/bootstrap.css"> <style type="text/css"> .container{ margin-top: 100px;} #avatar{ display: none} .avatar{ width: 60px; height: 60px;margin-left: 15px;cursor: pointer;} </style> </head> <body> <div class="container"> <div class="row"> <div class="col-md-6 col-md-offset-3"> <form action=""> {% for field in form %} <div class="form-group"> <label for="{{ field.id_for_label }}">{{ field.label }}</label> {{ field }} <span class="error pull-right"></span> </div> {% endfor %} <div class="form-group"> <label for="avatar">頭像 <img class="avatar" src="/static/img/default.png" alt=""> </label> <input type="file" id="avatar"> </div> <input type="button" class="btn btn-default login-btn reg_btn pull-right" value="提交"> </form> </div> </div> </div> {% csrf_token %} <script src="/static/js/jquery-3.2.1.min.js"></script> <script type="text/javascript"> //圖像預覽 $('#avatar').change(function () { var choose_file = $(this)[0].files[0]; //文件對象 var reader = new FileReader(); // 閱讀器對象 reader.readAsDataURL(choose_file); reader.onload = function (ev) { $('.avatar').attr('src',reader.result) }; {#$('.avatar').attr('src',reader.result) // 還沒讀完,就執行了這句了 出問題了!!#} //解決辦法 reader.onload }); // 註冊事件 $('.reg_btn').click(function () { 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("avatar",$('#avatar')[0].files[0]); formdata.append("csrfmiddlewaretoken",$('input[name="csrfmiddlewaretoken"]').val()); $.ajax({ url:'', type:'post', contentType:false, processData:false, data:formdata, success:function (data) { if(data.user){ //註冊成功 location.href = "/login/" }else{ //註冊失敗 //清空錯誤信息 $('form span').html(""); $('form .form-group').removeClass('has-error'); // 加載錯誤信息 $.each(data.error_dict,function (field,error_list) { // 全局 if(field == "__all__"){ $('#id_repeat_pwd').next().text(error_list[0]).css('color','red'); $('#id_repeat_pwd').parent().addClass('has-error') } $('#id_'+field).next().text(error_list[0]).css('color','red'); $('#id_'+field).parent().addClass('has-error') }) } } }) }) </script> </body> </html>
from django import forms from django.forms import widgets,ValidationError from app01.models import UserInfo class RegForm(forms.Form): user = forms.CharField(max_length=8,label='用戶名', widget=widgets.TextInput(attrs={'class':'form-control'})) pwd = forms.CharField(min_length=4,label='密碼', widget=widgets.PasswordInput(attrs={'class':'form-control'})) repeat_pwd = forms.CharField(min_length=4,label='確認密碼', widget=widgets.PasswordInput(attrs={'class': 'form-control'})) email = forms.EmailField(label='郵箱', widget=widgets.EmailInput(attrs={'class': 'form-control'})) # 局部鉤子 def clean_user(self): val = self.cleaned_data.get('user') ret = UserInfo.objects.filter(username = val) if not ret: return val else: raise ValidationError('該用戶已存在') # 校驗局部鉤子得時候 沒有辦法 拿到 全部得乾淨數據, # 如何 校驗 兩個 字段呢! 全局鉤子 # 全局鉤子 能獲得 任何一個乾淨得 數據 def clean(self):return self.cleaned_data def clean(self): if self.cleaned_data.get('pwd') == self.cleaned_data.get('repeat_pwd'): return self.cleaned_data else: raise ValidationError('兩次密碼不一致') from django.http import JsonResponse def reg(request): if request.method == 'POST': res = {'user':None,'error_dict':None} form = RegForm(request.POST) if form.is_valid(): print("clean:",form.cleaned_data) # {"user":'yuan','pwd':"123"} print(request.FILES) user = form.cleaned_data.get('user') pwd = form.cleaned_data.get('pwd') email = form.cleaned_data.get('email') avatar = request.FILES.get('avatar') if avatar: # 接受文件對象 將avatar文件對象下載到avatar字段對應的upload_to指定路徑 沒指定在 根目錄下 user = UserInfo.objects.create_user(username=user,password=pwd,email=email,avatar=avatar) else: user = UserInfo.objects.create_user(username=user, password=pwd, email=email) res['user'] = user.username else: print('error:',form.errors) #{"repear_pwd":['',''],"email":['',''],} res['error_dict'] = form.errors return JsonResponse(res) form = RegForm() return render(request,'reg.html',locals())
知識點1: jquery對象[0] jquery對象------------------>DOM <------------------ $(DOM) 知識點2: 請求形式: form get form post ajax get ajax post a標籤 get 地址欄 get 注意: form只有 get post ajax 有 get post put delete ... 查看 get 修改 post (增 post 刪 delete 更新 put) 知識點3: url_encoded http請求協議:{"user":"alex","pwd":123}-------------->"user=alex&pwd=123" form-data {"user":"alex","avatar":obj}-----------> "GET HTTP1.1 /upload/\r\n content—type='url_encoded'\r\n\r\nuser=alex&pwd=123" 請求頭: Content—Type:告訴服務器此次請求數據的格式,默認值:url_encoded if 上傳文件:Content—Type=form-data 知識點4: form對象渲染樣式: #方式1: {{form.as_p}} #方式2: {{form.user}} #方式3: {% for field in form %} <div> <label for="">{{ field.label }}</label> <div> {{ field }} </div> </div> {% endfor %} 博客系統的登陸 ---- 基於PIL模塊實現的驗證碼圖片 ---- 基於session保存驗證碼 ---- 刷新驗證碼 博客系統的註冊 基於ajax和form組件實現註冊 ---設計註冊頁面 self.fields:{"字段":字段規則} form.is_valid(): self.errors={} self.clean_data={} UserInfo.objects.create_user(username=user,password=pwd,email=email,avatar=avatar) 將avatar文件對象下載到avatar字段對應的upload_to指定路徑 (1) media配置: 針對: avatar = models.FileField(upload_to='avatars/', default="/avatars/default.png") avatar = models.ImageField(upload_to='avatars/', default="/avatars/default.png") MEDIA_ROOT=os.path.join(BASE_DIR,"blog","media") (2) MEDIA_URL="/media/" # media 配置 url(r'^media/(?P<path>.*)$', serve, {'document_root': settings.MEDIA_ROOT}),