Django組件介紹html
分頁器的使用前端
Formpython
modelFormgit
ormweb
cookie和sessionajax
中間件sql
信號數據庫
分頁器在頁面中很是常見,當數據庫條數數據過多時,頁面一次性顯示很差看,咱們就可使用頁面器,將數據分幾回顯示後端
一個簡單的分頁功能,能夠導入用
page_num = request.GET.get('page','1') try: page_num = int(page_num) if page_num <=0: page_num = 1 except Exception as e: page_num =1 #總數量 all_count = len(userlist) #每頁顯示爲10 頁 per_num = 10 #總頁碼數 total_page_num, more =divmod(all_count,per_num) if more: total_page_num += 1 #最多顯示的頁面數 max_show = 11 half_show = max_show//2 if total_page_num < max_show: page_start = 1 page_end = total_page_num elif page_num <= half_show: page_start =1 page_end =max_show elif page_num + half_show > total_page_num: page_start = total_page_num-max_show +1 page_end = total_page_num else: #起始頁面 page_start = page_num - half_show #終止頁面 page_end = page_num + half_show start =(page_num-1) * per_num end =page_num*per_num page_list = [] if page_num == 1: page_list.append('<li class="disabled"><a>上一頁</a></li>') else: page_list.append('<li ><a href="?page={}">上一頁</a></li>'.format(page_num - 1)) for i in range(page_start, page_end + 1): if i == page_num: page_list.append('<li class="active" ><a href="?page={}">{}</a></li>'.format(i, i)) else: page_list.append('<li><a href="?page={}">{}</a></li>'.format(i, i)) if page_num == total_page_num: page_list.append('<li class="disabled"><a>下一頁</a></li>') else: page_list.append('<li><a href="?page={}">下一頁</a></li>'.format(page_num + 1)) page_html = ''.join(page_list) return render(request, 'user_list.html', {'users': userlist[start:end], 'page_html': page_html})
django框架提供了一個form類,來處理web開發中的表單相關事項.form最常作的是對用戶輸入的內容進行驗證,爲此django的forms類提供了全面的內容驗證和保留用戶上次輸入數據的支持
form組件的兩大功能:
---對用戶提交的內容進行驗證(from表單/ajax)
---表留用戶上次輸入的內容
form組件的幾大用處:
1.校驗字段功能
1.首先先到導入forms這個模塊 from django import forms 2.本身寫一個類,並繼承forms.Form class Myform(forms.Form): #這行代碼的意思,name這字段最長爲8,最短爲3 name=forms.charField(max_length=8) def index(request): dic={'name':'zh'} #這裏就是類的實例化,傳的參數必須爲一個字典 myform =Myform(dic) #這是對象的綁定方式,它的返回值就是一個布爾值 # True表示你傳的dic這個字典知足form裏的條件,False就是不知足 # 咱們能夠經過判斷它,再進行邏輯操做,好比該字段符合你的要求,再怎麼操做 if myform.is_valid(): return HttpResponse('校驗成功') # 走到這一步,表明當中有字段不符合要求 # 它的返回值是一個對象,可是它繼承了字典,因此你能夠經過get取到錯誤提示 # 對了,你傳的字典的key值必需要和建立的類(Myform)要對應,而且只能多,不能少 # name_error = myform.errors.get('name') # 這樣你能夠取到name字段出錯的緣由了 name_error=myform.errors return HttpResponse('校驗失敗') ## 總結下:一、Myform的實例化必須傳字典 2、is_valid()返回值是布爾類型 三、errors 調用這個方法,返回值是對象,你能夠經過get取值
2.渲染標籤功能
form組件能夠在視圖函數中使用,也能夠在模板中使用
渲染方式一: <form action='' method='post'> 用戶名:{{myform:name}} <br> <input type='submit' value = '提交'></input> </form> # 這裏的{{myform:name}} 和你寫input框是同樣的效果,就是屬性比input框多一點 渲染方式二(推薦使用): <form action='' method='post'> {% for foo in myform%} {{ foo.lable }} : {{ foo }} <br> <input type='submit' value = '提交'></input> </form> # 頁面顯示都是同樣的,foo.lable不是用戶名,是name,可是你能夠在建立Myform類時 # 在CharFiel中添加lable='用戶名',這樣就好了。 渲染方式三: <form action='' method='post'> {{ myform.as_p }} <input type='submit' value = '提交'></input> </form> # 對,方式三就是這麼簡單,可是拓展性太差了,對不對,因此不推薦使用它
3.渲染錯誤信息功能
渲染錯誤信息,以前不是寫了error這個方法嘛,他就是裝着錯誤信息的對象, 其實就是讓它渲染到頁面上,這不就是很簡單嘛 拿渲染方式二來舉例子吧: <form action='' method='post'> {% for foo in myform%} {{ foo.lable }} : {{ foo }} <span>{{foo.errors.0}}</span><br> <input type='submit' value = '提交'></input> </form> # 來說下爲何不是用get去取錯誤信息,首先這個foo是什麼?它就是你建立的字段 # 因此直接經過索引取值就行了,那麼就應該知道foo.errors貌似就是一個列表對吧 # 模板渲染時我在後臺渲染好了,再返回到前臺的,那我能夠不能夠將錯誤信息傳到前臺 # 讓前臺執行DOM操做進行渲染呢? # 我以爲太麻煩,何況前端我。。。(你懂的)
4.組件的參數配置
其實在些Myform,下面的字段還有不少參數,我就寫寫大概有什麼用 max_length # 表明該字段最長爲多少 min_length # 表明該字段最短爲多少 error_messages # 這是設置錯誤信息的屬性 # 例子 error_messages= {'max_length': '最長八位', 'min_length': '最短三位', 'required': '不能爲空'} required # 默認值爲True,意思是你傳來的字段必須有它,沒有的話校驗失敗 widget=widgets.TextInput() # 你在模板渲染的時候,就會渲染成Input框,type爲text 還有其餘類型的input框,本身在看看吧 對了,在TextInput(),你能夠爲input添加屬性,attrs={'class':'abc'} 寫在括號裏面 lable #這個是否是上面講到了,lable='用戶名'
5.鉤子
局部鉤子 局部鉤子說白了就是寫一個函數,可是這個函數名必須爲clean_name,這個name是能夠改變的, 你定義的類裏,你想對哪一個字段寫鉤子函數,這個name就爲那個字段的名字,好比我想爲password這個 字段寫鉤子函數,那函數名就爲clean_password,就這樣。 那這個局部鉤子有什麼用了? 首先你的程序能走到局部鉤子這一步,就說明你傳的字典中的字段符合要求,這要記清楚,那麼咱們在 取值就從clean_data中取就行了,clean_data裏裝的是符合要求的數據,是一個字典。 咱們能夠從clean_data中取到相應的值再作一次邏輯處理,好比我寫clean_name這個局部鉤子, 我能夠拿到name,對這個name進行一些操做,名字開頭不能是數字,名字中不能有有什麼字符,這 些等等,看你本身的需求,邏輯代碼寫好了,最後return name 就行了 全局鉤子 全局鉤子其實做用差很少的,每一個字段你能夠進行局部鉤子進行邏輯書寫,這些處理完成以後,有須要的話, 你再進行全局處理,舉個例子就大概能明白,你在寫註冊用戶的時候,是否是有密碼,確認密碼,你能夠進行 佈局鉤子處理,處理完畢是否是在進行判斷,判斷他們是否相等,相等的話,就存到數據庫中,不相等就拋個 異常,對了對了,上面局部鉤子忘記寫異常,下面講講。 -----1、局部鉤子,全局鉤子所拋出異常的類型爲ValidationError,它是在下面這行代碼導入 from django.core.exceptions import ValidationError 2、局部鉤子拋出的異常會添加到該字段中的錯誤信息中,也就是myform.errors.get(字段名)中 三、而全局鉤子拋出的異常會添加到__all__中,myform.errors.get('__all__')中能夠取到
做用:
1.手動對單表進行增,刪,改,查,手動把orm操做獲取的數據渲染到模塊;(階段1)
2.Form組件(類),自動生成標籤(input,select),並對用戶輸入的數據作規則驗證;(階段2)
3.ModelForm顧名思義就Form和Django的Model數據庫模型結合體,能夠簡單,方便地對數據庫進行增長,編輯操做和驗證標籤的生成
使用ModelForm
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>Title</title> </head> <body> {{ form_obj.as_p }} {#<p>姓名:{{form_obj.name }}</p>#} </body> </html>
class BSForm(forms.ModelForm): def __init__(self, *args, **kwargs): super().__init__(*args, **kwargs) for filed in self.fields.values(): if not isinstance(filed, forms.BooleanField): filed.widget.attrs.update({'class': "form-control"}) class RegForm(BSForm): re_pwd = forms.CharField(widget=forms.PasswordInput, label='確認密碼') class Meta: model = models.UserProfile fields='__all__' #獲取所有的 exclude=['memo','is_active'] #刪除不想要的 labels = { 'username': '用戶名' #標籤 } widgets = { 'password': forms.PasswordInput(attrs={'class': "form-control", 'k1': 'v1'}), } error_messages = { 'password': { 'required': '必填的' } } def clean(self): pwd = self.cleaned_data.get('password', '') re_pwd = self.cleaned_data.get('re_pwd', '') if pwd == re_pwd: return self.cleaned_data self.add_error('re_pwd', '兩次密碼不一致') raise ValidationError('兩次密碼不一直') def reg(request): form_obj=RegForm() if request.method =="POST": form_obj=RegForm(request.POST) if form_obj.is_valid(): # print(form_obj.cleaned_data) # form_obj.cleaned_data.pop('re_pwd') # models.UserProfile.objects.create(**form_obj.cleaned_data) form_obj.save() return redirect(reverse('login')) return render(request,'reg.html',{'form_obj':form_obj})
--MVC框架中包括一個重要的部分,就是ORM,它實現了數據模型與數據庫的解耦,即數據模型的設計不須要依賴於特定的數據庫,經過簡單的配置就能夠輕鬆更換數據庫
--ORM是'對象-關係-映射'的簡稱 ,主要任務是:
*根據對象的類型生成表結構
*將對象,列表的操做,轉換爲sql語句
*將sql查詢到的結果轉換爲對象,列表
--這極大地減輕了開發人員的工做量,不須要面對因數據庫變動而致使的無效勞動
--Django中的模型包含存儲數據的字段和約束,對應着數據庫中惟一的表
1.在models.py中定義模型類,要求繼承自models.Model 2.把應用加入settings.py文件的installed_app項 3.生成遷移文件 4.執行遷移生成表 5.使用模型類進行crud操做
在模型中定義屬性,會生成表中的字段
django根據屬性的類型肯定如下信息:
當前選擇的數據庫支持字段的類型
渲染管理表單時使用的默認html控件
在管理站點最低限度的驗證
django會爲表增長自動增加的主鍵列,每一個模型只能有一個主鍵列,若是使用選項設置某屬性爲主鍵列後,則django不會再生成默認的主鍵列
屬性命名限制
不能是python的保留關鍵字
因爲django的查詢方式,不容許使用連續的下劃線
定義屬性時,須要字段類型 字段類型被定義在django.db.models.fields目錄下,爲了方便使用,被導入到django.db.models中 使用方式 導入from django.db import models 經過models.Field建立字段類型的對象,賦值給屬性 對於重要數據都作邏輯刪除,不作物理刪除,實現方法是定義isDelete屬性,類型爲BooleanField,默認值爲False 字段類型 AutoField:一個根據實際ID自動增加的IntegerField,一般不指定 若是不指定,一個主鍵字段將自動添加到模型中 BooleanField:true/false 字段,此字段的默認表單控制是CheckboxInput NullBooleanField:支持null、true、false三種值 CharField(max_length=字符長度):字符串,默認的表單樣式是 TextInput TextField:大文本字段,通常超過4000使用,默認的表單控件是Textarea IntegerField:整數 DecimalField(max_digits=None, decimal_places=None):使用python的Decimal實例表示的十進制浮點數 DecimalField.max_digits:位數總數 DecimalField.decimal_places:小數點後的數字位數 FloatField:用Python的float實例來表示的浮點數 DateField[auto_now=False, auto_now_add=False]):使用Python的datetime.date實例表示的日期 參數DateField.auto_now:每次保存對象時,自動設置該字段爲當前時間,用於"最後一次修改"的時間戳,它老是使用當前日期,默認爲false 參數DateField.auto_now_add:當對象第一次被建立時自動設置當前時間,用於建立的時間戳,它老是使用當前日期,默認爲false 該字段默認對應的表單控件是一個TextInput. 在管理員站點添加了一個JavaScript寫的日曆控件,和一個「Today"的快捷按鈕,包含了一個額外的invalid_date錯誤消息鍵 auto_now_add, auto_now, and default 這些設置是相互排斥的,他們之間的任何組合將會發生錯誤的結果 TimeField:使用Python的datetime.time實例表示的時間,參數同DateField DateTimeField:使用Python的datetime.datetime實例表示的日期和時間,參數同DateField FileField:一個上傳文件的字段 ImageField:繼承了FileField的全部屬性和方法,但對上傳的對象進行校驗,確保它是個有效的image 字段選項 經過字段選項,能夠實現對字段的約束 在字段對象時經過關鍵字參數指定 null:若是爲True,Django 將空值以NULL 存儲到數據庫中,默認值是 False blank:若是爲True,則該字段容許爲空白,默認值是 False 對比:null是數據庫範疇的概念,blank是表單驗證證範疇的 db_column:字段的名稱,若是未指定,則使用屬性的名稱 db_index:若值爲 True, 則在表中會爲此字段建立索引 default:默認值 primary_key:若爲 True, 則該字段會成爲模型的主鍵字段 unique:若是爲 True, 這個字段在表中必須有惟一值 關係 關係的類型包括 ForeignKey:一對多,將字段定義在多的端中 ManyToManyField:多對多,將字段定義在兩端中 OneToOneField:一對一,將字段定義在任意一端中 能夠維護遞歸的關聯關係,使用'self'指定,詳見「自關聯」 用一訪問多:對象.模型類小寫_set
增: models.UserInfo.object.create(name=new_name) 刪: models.UserInfo.object.get(id=xxx,None) models.delete() 改: obj = models.UserInfo.object.get(id=xx,None) obj = new_xxx obj.save() #至關於修改後提交數據 查 querylist=models.Entry.objects.all() print([e.title for e in querylist]) print([e.title for e in querylist]) entry = models.Entry.objects.get(id=?)
cookies是瀏覽器爲web服務器存儲的一個信息,每次瀏覽器從某個服務器請求頁面時,都會自動帶上之前收到的cookie.cookie保存在客戶端,安全性較差,注意不要保存沒敢信息.
--網絡登陸
--購物車
def login(request): if request.method == 'GET': return render(request,'login2.html') if request.method == 'POST': u = request.POST.get('username') p = request.POST.get('pwd') dic = user_info.get(u) if not dic: return render(request,'login2.html') current_date = datetime.datetime.utcnow() current_date = current_date + datetime.timedelta(seconds=10) if dic['pwd'] == p: res = redirect('/myapp/index') # res.set_cookie('username',u,max_age=10) #對cookie設置了超時時間和安全設置 res.set_cookie('username',u,expires=current_date,httponly=True) # res.set_signed_cookie('username',u,salt="121221") return res else: return render(request,'login2.html')
詳情頁面,若是cookie 驗證經過則進入index頁面,不然刷新進入登陸頁面
def auth(func): def inner(request,*args,**kwargs): v = request.COOKIES.get('username') if not v: return redirect('/myapp/login') return func(request,*args,**kwargs) return inner @auth def index(request): v = request.COOKIES.get('username') return render(request,'index2.html',{'current_user':v})
session就是保存在後臺數據或者緩存中的一個鍵值對,一樣的存儲着用戶信息,爲更好的保護用戶隱私,實際上是對前端cookie的一個升級的保護措施
當登陸成功後,會向後臺數據庫 與 前端 Cookie同時發放一段隨機字符串,分別保存在後臺的session中,前端 寫到用戶瀏覽器中,用戶下次登陸時候 拿着瀏覽器存着的sessionID當作KEY去後臺數據庫中匹配進行驗證登陸便可拿到用戶相關信息,能夠防止敏感信息直接暴露在瀏覽器上 做者:TianTianBaby223 連接:https://www.jianshu.com/p/a2d696364501 來源:簡書 簡書著做權歸做者全部,任何形式的轉載都請聯繫做者得到受權並註明出處。
Django下用session實現登陸驗證
def sessionLogin(request): if request.method == "GET": return render(request,'sessionLogin.html') elif request.method == "POST": user = request.POST.get('user') pwd = request.POST.get('pwd') if user == 'root' and pwd =="123": #生成隨機字符串 #寫到用戶瀏覽器 #保存到session中 #在隨機字符串對應的字典中設置相關內容... request.session['username'] = user request.session['is_login'] = True if request.POST.get('rmb',None) == '1': request.session.set_expiry(10) return redirect('/myapp/sessionindex') else: return render(request, 'sessionLogin.html')
詳情頁邏輯
def sessionindex(request): #獲取當前用戶的隨機字符串 #根據隨機字符串獲取對應信息 if request.session.get('is_login',None): return render(request,'sessionindex.html',{'username':request.session['username']}) else: return HttpResponse('get out')
定義:介於request(請求)與response(響應)處理之間的一道處理過程,相對比較輕量級,位於web服務端與url路由層之間
MIDDLEWARE = [
'django.middleware.security.SecurityMiddleware', #一些安全設置,好比xss腳本過濾
'django.contrib.sessions.middleware.SessionMiddleware',#session支持中間件,加入這個中間件,會在數據庫中生成一個django_session的表。
'django.middleware.common.CommonMiddleware', #通用中間件,會處理一些url
'django.middleware.csrf.CsrfViewMiddleware', #跨域請求僞造中間件,加入這個中間件,在提交表單的時候會必須加入csrf_token,cookie中也會生成一個名叫csrftoken的值,也會在header中加入一個HTTP_X_CSRFTOKEN的值來放置CSRF攻擊。
'django.contrib.auth.middleware.AuthenticationMiddleware', #用戶受權中間件。他會在每一個HttpRequest對象到達view以前添加當前登陸用戶的user屬性,也就是你能夠在view中經過request訪問user。
'django.contrib.messages.middleware.MessageMiddleware',#消息中間件。展現一些後臺信息給前端頁面。若是須要用到消息,還須要在INSTALLED_APPS中添加django.contrib.message纔能有效。若是不須要,能夠把這兩個都刪除。
'django.middleware.clickjacking.XFrameOptionsMiddleware',#防止經過瀏覽器頁面跨Frame出現clickjacking(欺騙點擊)攻擊出現。
'A_orm.middlewares.auth.AuthenticationMiddleware',
]
請求進來是自上而下,經過反射找到類,用for循環來執行,能夠自定義中間件,但也要寫入MIDDLEWAR中
1、process_request(self,request) #請求完執行 2、process_view(self, request, callback, callback_args, callback_kwargs) #若是有返回值,跳轉到最後一箇中間件,執行最後一箇中間件的response方法,逐步返回 3、process_template_response(self,request,response) #默認不執行,只有在視圖函數的返回對象中有render方法纔會執行 4、process_exception(self, request, exception) #默認啥也不執行,在視圖函數出現錯誤是才執行,返回錯誤信息 5、process_response(self, request, response) #響應執行
1、作IP限制 放在 中間件類的列表中,阻止某些IP訪問了; 2、URL訪問過濾 若是用戶訪問的是login視圖(放過) 若是訪問其餘視圖(須要檢測是否是有session已經有了放行,沒有返回login),這樣就免得在 多個視圖函數上寫裝飾器了! 3、緩存(還記得CDN嗎?) 客戶端請求來了,中間件去緩存看看有沒有數據,有直接返回給用戶,沒有再去邏輯層 執行視圖函數
執行順序:
1.咱們要在app01文件下建立一個文件(middlewares)文件,在下面建立一個.py文件寫入自定義中間件
2.在setting裏面添加中間件,文件路徑+功能
3.在views.py大家調用便可.
def index(request): print('1')
定義:用於框架執行操做時解耦,就是一些動做發生的時候,信號容許特定的發送者去提醒一些接受者
Model signals pre_init # django的model執行其構造方法前,自動觸發 post_init # django的model執行其構造方法後,自動觸發 pre_save # django的model對象保存前,自動觸發 post_save # django的model對象保存後,自動觸發 pre_delete # django的model對象刪除前,自動觸發 post_delete # django的model對象刪除後,自動觸發 m2m_changed # django的model中使用m2m字段操做第三張表(add,remove,clear)先後,自動觸發 class_prepared # 程序啓動時,檢測已註冊的app中modal類,對於每個類,自動觸發 from django.db.models.signals import pre_init, post_init from django.db.models.signals import pre_save, post_save
Management signals pre_migrate # 執行migrate命令前,自動觸發 post_migrate # 執行migrate命令後,自動觸發
Request/response signals request_started # 請求到來前,自動觸發 request_finished # 請求結束後,自動觸發 got_request_exception # 請求異常後,自動觸發 from django.core.signals import request_finished from django.core.signals import request_started
setting_changed # 使用test測試修改配置文件時,自動觸發 template_rendered # 使用test測試渲染模板時,自動觸發 from django.test.signals import setting_changed from django.test.signals import template_rendered
connection_created # 建立數據庫鏈接時,自動觸發 from django.db.backends.signals import connection_created