Django知識補充
阿新 • • 發佈:2019-01-03
一、檔案上傳
1、三種方式
-
通過form表單提交實現基本上傳
-
通過From類上傳
-
ajax上傳
from django.shortcuts import render,HttpResponse from django import forms from django.forms import fields class UploadForm(forms.Form): user = fields.CharField() img = fields.FileField() def upload(request): '''上傳檔案'''if request.method == 'GET': return render(request,'upload.html') else: ''' # 基於Form也可以上傳,這裡還做了驗證 obj = UploadForm(request.POST,request.FILES) if obj.is_valid(): user = obj.cleaned_data['user'] img = obj.cleaned_data['img']''' #img是物件,封裝了檔案大小、名稱、內容。。。 img = request.FILES.get('img') print(img.name) print(img.size) #將上傳檔案寫入本地 f = open(img.name,'wb') #上傳是一點一點的,所以不能一下子拿到全部,需要迴圈 for line in img.chunks(): f.write(line) f.close() returnHttpResponse('上傳成功')
二、Models補充
1、欄位
AutoField(Field) - int自增列,必須填入引數 primary_key=True BigAutoField(AutoField) - bigint自增列,必須填入引數 primary_key=True 注:當model中如果沒有自增列,則自動會建立一個列名為id的列 from django.db import models class UserInfo(models.Model): # 自動建立一個列名為id的且為自增的整數列 username = models.CharField(max_length=32) class Group(models.Model): # 自定義自增列 nid = models.AutoField(primary_key=True) name = models.CharField(max_length=32) SmallIntegerField(IntegerField): - 小整數 -32768 ~ 32767 PositiveSmallIntegerField(PositiveIntegerRelDbTypeMixin, IntegerField) - 正小整數 0 ~ 32767 IntegerField(Field) - 整數列(有符號的) -2147483648 ~ 2147483647 PositiveIntegerField(PositiveIntegerRelDbTypeMixin, IntegerField) - 正整數 0 ~ 2147483647 BigIntegerField(IntegerField): - 長整型(有符號的) -9223372036854775808 ~ 9223372036854775807 BooleanField(Field) - 布林值型別 NullBooleanField(Field): - 可以為空的布林值 CharField(Field) - 字元型別 - 必須提供max_length引數, max_length表示字元長度 TextField(Field) - 文字型別 EmailField(CharField): - 字串型別,Django Admin以及ModelForm中提供驗證機制 IPAddressField(Field) - 字串型別,Django Admin以及ModelForm中提供驗證 IPV4 機制 GenericIPAddressField(Field) - 字串型別,Django Admin以及ModelForm中提供驗證 Ipv4和Ipv6 - 引數: protocol,用於指定Ipv4或Ipv6, 'both',"ipv4","ipv6" unpack_ipv4, 如果指定為True,則輸入::ffff:192.0.2.1時候,可解析為192.0.2.1,開啟刺功能,需要protocol="both" URLField(CharField) - 字串型別,Django Admin以及ModelForm中提供驗證 URL SlugField(CharField) - 字串型別,Django Admin以及ModelForm中提供驗證支援 字母、數字、下劃線、連線符(減號) CommaSeparatedIntegerField(CharField) - 字串型別,格式必須為逗號分割的數字 UUIDField(Field) - 字串型別,Django Admin以及ModelForm中提供對UUID格式的驗證 FilePathField(Field) - 字串,Django Admin以及ModelForm中提供讀取資料夾下檔案的功能 - 引數: path, 資料夾路徑 match=None, 正則匹配 recursive=False, 遞迴下面的資料夾 allow_files=True, 允許檔案 allow_folders=False, 允許資料夾 FileField(Field) - 字串,路徑儲存在資料庫,檔案上傳到指定目錄 - 引數: upload_to = "" 上傳檔案的儲存路徑 storage = None 儲存元件,預設django.core.files.storage.FileSystemStorage ImageField(FileField) - 字串,路徑儲存在資料庫,檔案上傳到指定目錄 - 引數: upload_to = "" 上傳檔案的儲存路徑 storage = None 儲存元件,預設django.core.files.storage.FileSystemStorage width_field=None, 上傳圖片的高度儲存的資料庫欄位名(字串) height_field=None 上傳圖片的寬度儲存的資料庫欄位名(字串) DateTimeField(DateField) - 日期+時間格式 YYYY-MM-DD HH:MM[:ss[.uuuuuu]][TZ] DateField(DateTimeCheckMixin, Field) - 日期格式 YYYY-MM-DD TimeField(DateTimeCheckMixin, Field) - 時間格式 HH:MM[:ss[.uuuuuu]] DurationField(Field) - 長整數,時間間隔,資料庫中按照bigint儲存,ORM中獲取的值為datetime.timedelta型別 FloatField(Field) - 浮點型,小數位越多,約不精確,小數建議使用下面欄位 DecimalField(Field) - 10進位制小數 - 引數: max_digits,小數總長度 decimal_places,小數位長度 BinaryField(Field) - 二進位制型別
2、欄位引數
null 資料庫中欄位是否可以為空 db_column 資料庫中欄位的列名 default 資料庫中欄位的預設值 primary_key 資料庫中欄位是否為主鍵 db_index 資料庫中欄位是否可以建立索引 unique 資料庫中欄位是否可以建立唯一索引 unique_for_date 資料庫中欄位【日期】部分是否可以建立唯一索引 unique_for_month 資料庫中欄位【月】部分是否可以建立唯一索引 unique_for_year 資料庫中欄位【年】部分是否可以建立唯一索引 verbose_name Admin中顯示的欄位名稱 blank Admin中是否允許使用者輸入為空 editable Admin中是否可以編輯,直接隱藏了,form中是變灰色 help_text Admin中該欄位的提示資訊 choices Admin中顯示選擇框的內容,用不變動的資料放在記憶體中從而避免跨表操作 如:gf = models.IntegerField(choices=[(0, '何穗'),(1, '大表姐'),],default=1) error_messages 自定義錯誤資訊(字典型別),從而定製想要顯示的錯誤資訊; 字典健:null, blank, invalid, invalid_choice, unique, and unique_for_date 如:{'null': "不能為空.", 'invalid': '格式錯誤'} validators 自定義錯誤驗證(列表型別),從而定製想要的驗證規則 from django.core.validators import RegexValidator from django.core.validators import EmailValidator,URLValidator,DecimalValidator,\ MaxLengthValidator,MinLengthValidator,MaxValueValidator,MinValueValidator 如: test = models.CharField( max_length=32, error_messages={ 'c1': '優先錯資訊1', 'c2': '優先錯資訊2', 'c3': '優先錯資訊3', }, validators=[ RegexValidator(regex='root_\d+', message='錯誤了', code='c1'), RegexValidator(regex='root_112233\d+', message='又錯誤了', code='c2'), EmailValidator(message='又錯誤了', code='c3'), ] )
例項:
from django.db import models class UserInfo(models.Model): username = models.CharField( null=True, #可以為空 db_column='user', #表中顯示的列名 max_length=32, #字串欄位必須有最大長度 db_index=True, #建立索引,只能加速查詢 unique=True, #加速查詢,限制列值唯一 #primary_key=True, #加速查詢,限制列值唯一,不能為空 ) #生成下拉框 user_type = models.IntegerField( choices = [ (1,'普通使用者'), (2,'超級使用者'), (3,'VIP使用者'), ] ) part = models.ForeignKey( to = 'Part', to_field = 'id', on_delete = models.CASCADE, # related_name='part', limit_choices_to={'id__gt':1} #只顯示ID大於1的 ) def __str__(self): return self.username class Part(models.Model): caption = models.CharField(max_length=32) def __str__(self): return self.caption
3、多表關係以及引數
ForeignKey(ForeignObject) # ForeignObject(RelatedField) to, # 要進行關聯的表名 to_field=None, # 要關聯的表中的欄位名稱 on_delete=None, # 當刪除關聯表中的資料時,當前表與其關聯的行的行為 - models.CASCADE,刪除關聯資料,與之關聯也刪除 - models.DO_NOTHING,刪除關聯資料,引發錯誤IntegrityError - models.PROTECT,刪除關聯資料,引發錯誤ProtectedError - models.SET_NULL,刪除關聯資料,與之關聯的值設定為null(前提FK欄位需要設定為可空) - models.SET_DEFAULT,刪除關聯資料,與之關聯的值設定為預設值(前提FK欄位需要設定預設值) - models.SET,刪除關聯資料, a. 與之關聯的值設定為指定值,設定:models.SET(值) b. 與之關聯的值設定為可執行物件的返回值,設定:models.SET(可執行物件) def func(): return 10 class MyModel(models.Model): user = models.ForeignKey( to="User", to_field="id" on_delete=models.SET(func),) related_name=None, # 反向操作時,使用的欄位名,用於代替 【表名_set】 如: obj.表名_set.all() related_query_name=None, # 反向操作時,使用的連線字首,用於替換【表名】 如: models.UserGroup.objects.filter(表名__欄位名=1).values('表名__欄位名') limit_choices_to=None, # 在Admin或ModelForm中顯示關聯資料時,提供的條件: # 如: - limit_choices_to={'nid__gt': 5} - limit_choices_to=lambda : {'nid__gt': 5} from django.db.models import Q - limit_choices_to=Q(nid__gt=10) - limit_choices_to=Q(nid=8) | Q(nid__gt=10) - limit_choices_to=lambda : Q(Q(nid=8) | Q(nid__gt=10)) & Q(caption='root') db_constraint=True # 是否在資料庫中建立外來鍵約束 parent_link=False # 在Admin中是否顯示關聯資料 OneToOneField(ForeignKey) to, # 要進行關聯的表名 to_field=None # 要關聯的表中的欄位名稱 on_delete=None, # 當刪除關聯表中的資料時,當前表與其關聯的行的行為 ###### 對於一對一 ###### # 1. 一對一其實就是 一對多 + 唯一索引 # 2.當兩個類之間有繼承關係時,預設會建立一個一對一欄位 # 如下會在A表中額外增加一個c_ptr_id列且唯一: class C(models.Model): nid = models.AutoField(primary_key=True) part = models.CharField(max_length=12) class A(C): id = models.AutoField(primary_key=True) code = models.CharField(max_length=1) ManyToManyField(RelatedField) to, # 要進行關聯的表名 related_name=None, # 反向操作時,使用的欄位名,用於代替 【表名_set】 如: obj.表名_set.all() related_query_name=None, # 反向操作時,使用的連線字首,用於替換【表名】 如: models.UserGroup.objects.filter(表名__欄位名=1).values('表名__欄位名') limit_choices_to=None, # 在Admin或ModelForm中顯示關聯資料時,提供的條件: # 如: - limit_choices_to={'nid__gt': 5} - limit_choices_to=lambda : {'nid__gt': 5} from django.db.models import Q - limit_choices_to=Q(nid__gt=10) - limit_choices_to=Q(nid=8) | Q(nid__gt=10) - limit_choices_to=lambda : Q(Q(nid=8) | Q(nid__gt=10)) & Q(caption='root') symmetrical=None, # 僅用於多對多自關聯時,symmetrical用於指定內部是否建立反向操作的欄位 # 做如下操作時,不同的symmetrical會有不同的可選欄位 models.BB.objects.filter(...) # 可選欄位有:code, id, m1 class BB(models.Model): code = models.CharField(max_length=12) m1 = models.ManyToManyField('self',symmetrical=True) # 可選欄位有: bb, code, id, m1 class BB(models.Model): code = models.CharField(max_length=12) m1 = models.ManyToManyField('self',symmetrical=False) through=None, # 自定義第三張表時,使用欄位用於指定關係表 through_fields=None, # 自定義第三張表時,使用欄位用於指定關係表中那些欄位做多對多關係表 from django.db import models class Person(models.Model): name = models.CharField(max_length=50) class Group(models.Model): name = models.CharField(max_length=128) members = models.ManyToManyField( Person, through='Membership', through_fields=('group', 'person'), ) class Membership(models.Model): group = models.ForeignKey(Group, on_delete=models.CASCADE) person = models.ForeignKey(Person, on_delete=models.CASCADE) inviter = models.ForeignKey( Person, on_delete=models.CASCADE, related_name="membership_invites", ) invite_reason = models.CharField(max_length=64) db_constraint=True, # 是否在資料庫中建立外來鍵約束 db_table=None, # 預設建立第三張表時,資料庫中表的名稱
三、Django總結
1、Django的一個請求週期(請求和相應HTTP),請求和相應都是以字串的形式 -- a、傳送HTTP請求; -- b、伺服器接收,根據請求頭中的URL在路由關係表中進行匹配(從上到下); -- c、匹配成功後,執行指定的views函式; 寫檢視函式的兩種方式:FBV CBV URL--》對應一個函式--》這種模式叫FBV url(r'login/', views.login) def login(request) URL--》對應一個類--》這種模式叫CBV 以POST方式傳送請求,執行post方法,以GET方式傳送請求,執行get方法; View類中有一個方法dispatch來根據請求方式判斷執行什麼方法,我們可以自定義這個方法 http_method_names = ['get', 'post', 'put', 'patch', 'delete', 'head', 'options', 'trace'] from django.view import View class Cbv(View): def dispatch(self, request, *args, **kwargs): print('dispatch....') ret = super(Cbv,self).dispatch(self.request,*args,**kwargs) return ret def get(self,request): return render(request,'cbv.html') def post(self,request): return HttpResponse('cbv.post') urls.py: url(r'cbv/', views.CBV.as_view()) cbv.html: <body> <form action="/cbv/" method="POST"> <input type="text"/> <input type="submit"/> </form> </body> -- d、業務處理 -- 可以根據個人需求自定製 -- 操作資料庫 - 原生SQL語句 - Django ORM ==最後得到返回給使用者的結果== -- 響應內容 - 響應頭 - 響應體 響應頭沒有內容,我們可以主動給它返回內容 def post(self,request): ret = HttpResponse('cbv.post') ret['k1'] = 'v1' ret.set_cookie('k2','v2') ''' 頭:k1=v1 cookies:k2=v2 體:cbv.post ''' return ret 2、建立Django專案的基本流程 -- 建立新專案 -- 建立APP -- 建立static資料夾,settings配置靜態檔案路徑 -- 註冊APP INSTALLED_APPS -- 建立templates資料夾,settings配置模板檔案路徑 'DIRS': [os.path.join(BASE_DIR,'templates')], 3、ORM 多對多操作 #多對多新增,書籍類中有authors = models.ManyToManyField('Author') #增 book_obj = Book.objects.get(id=4) book_obj.authors.add(1) book_obj.authors.add(*[1,2,]) #刪 book_obj = Book.objects.get(id=4) book_obj.authors.remove(1) book_obj.authors.remove([1,2,]) book_obj.authors.clear() #重置,以設定的為準,已經有的不動,新內容裡沒有的就刪除 book_obj.authors.set([1,2,3]) #查 #所有書籍名稱和對應的作者名 book_list = Book.objects.all().values('name','authors__name') #列舉ID=1的書籍的所有作者 #方式一 book_obj = Book.objects.get(id=1) aut_obj = book_obj.authors.all() #方式二 Book.objects.filter(id=1).values('authors__name') #列舉作者charlie的所有書籍 Book.objects.filter(authors__name="charlie") 4、跨多張表查詢 class Book(models.Model): '''書籍''' name = models.CharField(max_length=20) price = models.IntegerField() pub_data = models.DateField() authors = models.ForeignKey('Author',on_delete=models.CASCADE) class Author(models.Model): '''作者''' name = models.CharField(max_length=20) age = models.IntegerField(default=20) country = models.ForeignKey('Country',on_delete=models.CASCADE) class Country(models.Model): '''國家''' name = models.CharField(max_length=20) #所有中國籍作者出的所有書籍 Book.objects.filter(authors__country__name='China') #正向查詢:Book.objects.filter(authors__name='charlie') #反向查詢: obj = Authors.objects.filter(name='charlie').first() obj.book_set.all() #沒有外來鍵的表裡其實隱藏了一個欄位:類名_set,也可以修改這個欄位名 class Book(models.Model): authors = models.ForeignKey('Author',on_delete=models.CASCADE,related_name='book') obj = Authors.objects.filter(name='charlie').first() book_list = obj.book.all()#作者對應的所有書籍物件查詢集[obj(name,price,..),obj(name,price,..),] 5、QuerySet內部有三種資料型別: -- 字典:values()得到,用['name']取值 -- 元組:value_list得到 -- 物件:all\filter得到,用點取值 6、-- 類代表資料庫表 -- 類的物件代指資料庫的一行記錄 -- ForeignKey欄位代指關聯表中的一行資料(關聯類的物件) -- 正向:fk欄位 -- 反向:小寫類名_set(預設),自定義ForeignKey(related_name='book') 一般不做反向查詢,進行兩次SQL操作,效率低; 7、一對多:這兩種操作相當於left join 連表操作,以查詢的表為主表,會顯示所有主表內容 Students.objects.all().values('name','classes__name') 顯示所有的學生資訊,沒有學生的班級不顯示 Classes.objects.all().values('name','students_set__name') 顯示所有的班級資訊,沒有學生的班級顯示None 8、select 標籤 - 單選 $().val() $().val(2) - 多選 $().val([1,2,3]) 9、靜態資料夾模板 - js(js檔案) - css(css檔案) - plugins(bootstrap,font-awesome等外掛) 10、JavaScript中把 物件轉換成字串 -- str = JSON.stringify({'k':'v'}) 字串轉換成物件 -- dict = JSON.parse(str) $.ajax({ url:'/del_student/', type:'GET', data:{nid:rowId}, datatype:'JSON',//ajax內部會自動轉換 success:function (arg) { //arg已經是物件了 } }) 11、jQuery事件委託 -- .on和.delegate()效果一樣,不過delegate前兩個引數要調換位置 $('要繫結標籤的上級標籤').on('click','要繫結的標籤',function(){}) 12、總結 新URL方式(點選跳轉到新的頁面): -- 獨立的頁面 -- 資料量大或條目多時,使用這個方便 對話方塊方式(ajax偷偷發送): -- 資料量小或條目少時使用 -- 此時新增資料,需要考慮當前頁、td中的自定義屬性 -- 資料量大時,工作量很大 如果不是強制要求使用對話方塊方式,建議使用新URL方式; 如果是刪除操作,建議用ajax方式; 13、ajax傳送checkbox資料,就是列表, var values = [1,2,3,4] $.ajax({ url:'/edit_student/', type:'POST', data:{'k':values}, traditional:true, success:function (arg){} }) error:function(){}//出錯自動觸發 views函式獲取資料方式: v = request.POST.getlist('k') 注意:data字典裡不能巢狀字典直接傳送過去,如果非要傳送需要JSON轉換一下 14、使用serialize就可以獲取整個form表單裡的所有資料,也是字典格式 $.ajax({ data:$('#fm').serialize(), }) 15、XSS攻擊:跨站指令碼攻擊,其實就是使用者寫了一段js程式碼,讓其他人訪問時執行這個指令碼; 如果有人在部落格下面評論輸入一下程式碼,會直接影響其他使用者瀏覽這篇部落格, 大家都陷入一個死迴圈 <script> for(var i=0;i<9999;i++){ alert(i); } </script> 攻擊方式二: <script> 獲取本地cookie,傳送到另外一個網站或程式 </script> 16、null=True,資料庫表中是否可以為空 blank=True,使用者輸入是否可以為空