django怎麼下載安裝?css
cmd中 PIP方式安裝django pip3 install django==1.11.9 pip3 install django==1.11.9 -i http://xxxxxx 指定源 pycham中裝模塊的地方安裝 或界面下Terminal安裝 File | Settings | Project: tushu | Project Interpreter
django怎麼建立啓動項目?html
建立項目 django-admin startproject mysite 建立了一個名爲"mysite"的Django 項目 啓動項目 python manage.py runserver 默認是127.0.0.1:8000 python manage.py runserver 127.0.0.1 默認端口號是8000 python manage.py runserver 127.0.0.1:8001 pycham 建立 注意不要用虛擬環境建立
django怎麼建立應用?前端
python manage.py startapp book 實際也是建立了一個文件夾book ps注意 本身手動建立須要在配置文件 註冊app
列如註冊了app01的apppython
列如註冊了api的appmysql
配置了django內置的app 也能夠加入本身註冊的app INSTALLED_APPS = [ 'django.contrib.admin', 'django.contrib.auth', 'django.contrib.contenttypes', 'django.contrib.sessions', 'django.contrib.messages', 'django.contrib.staticfiles', 'app01.apps.App01Config', ]
控制能夠訪問的網段jquery
ALLOWED_HOSTS = []
中間件linux
MIDDLEWARE = [ 'django.middleware.security.SecurityMiddleware', 'django.contrib.sessions.middleware.SessionMiddleware', 'django.middleware.common.CommonMiddleware', 'django.middleware.csrf.CsrfViewMiddleware', 'django.contrib.auth.middleware.AuthenticationMiddleware', 'django.contrib.messages.middleware.MessageMiddleware', 'django.middleware.clickjacking.XFrameOptionsMiddleware', ]
數據庫git
DATABASES = { 'default': { 'ENGINE': 'django.db.backends.sqlite3', 'NAME': os.path.join(BASE_DIR, 'db.sqlite3'), } }
HTTP協議詳細https://www.cnblogs.com/clschao/articles/9230431.html HTTP協議是什麼? 什麼是無狀態 無鏈接? HTTP請求與響應信息格式? http的請求方法? get請求和post的請求的區別? ttp的狀態碼? HTTP協議有什麼用? HTTP協議有什麼方法,怎麼使用?
1. 超文本傳輸協議(HTTP,HyperText Transfer Protocol)是互聯網上應用最爲普遍的一種網絡協議。是WWW (World Wide Web)實現數據通訊的基石。 2. 它是一種應用層協議(OSI七層模型的最頂層),它基於TCP/IP通訊協議來傳遞數據(HTML 文件, 圖片文件, 查詢結果等)。 3. HTTP協議用於客戶端和服務端之間的通訊,經過請求和響應的交互達成通訊(確定是先從客戶端開始創建通訊的,服務器端在沒有接收到任何請求以前不會發送響應)。 4. HTTP是 無狀態 無鏈接 的協議,爲了實現指望的保存狀態的功能,引入了Cookie技術。 引伸 什麼是無狀態 無鏈接? 無狀態就是 使用HTTP協議,每當有新的請求發送時,就會有對應的新響應產生。協議自己並不保留以前一切的請求或響應報文的信息。 無鏈接就是 每次鏈接只處理一個請求。服務器處理完客戶的請求,並收到客戶的應答後,即斷開鏈接
請求消息格式:請求行\請求頭部\空行\請求數據 請求行:GET 路徑 HTTP/1.1 響應消息格式:響應行\響應頭部\空行\響應數據 響應行: HTTP/1.1 狀態碼 狀態描述 引伸 http的請求方法? get\post\put\delete\head\options\trace\connect\ get請求和post的請求的區別? get請求 請求數據部分是沒有數據的,get請求的數據在url上,在請求行裏面,有大小限制,常見的get請求方式: 瀏覽器輸入網址,a標籤 post請求 請求數據在請求體(請求數據部分) ,數據沒有大小限制, 常見方式:form表單提交數據 http的狀態碼? 1xx請求被接受可是還在處理當中 2xx請求成功 3xx重定向(301永久重定向和302臨時重定向) 4xx客戶端錯誤(請求錯誤) 5xx服務器錯誤 http協議 請求信息格式 GET / HTTP/1.1 請求行 Host: 127.0.0.1:8003 請求頭 Connection: keep-alive Cache-Control: max-age=0 Upgrade-Insecure-Requests: 1 User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/75.0.3770.100 Safari/537.36 Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3 Accept-Encoding: gzip, deflate, br Accept-Language: zh-CN,zh;q=0.9 #空行 請求數據 username=ziwen password=666
做用:在瀏覽器與服務器間傳送文檔。
中間件是一個用來處理Django的請求和響應的框架級別的鉤子 中間件顧名思義,是介於request與response處理之間的一道處理過程,相對比較輕量級,而且在全局上改變django的輸入與輸出。由於改變的是全局,因此須要謹慎實用,用很差會影響到性能。
3步驟web
第一步 在應用下鍵立一個文件夾(隨意取名字)在文件夾下建立一個py文件名字隨意取 第2步 在py文件中引入from django.utils.deprecation import MiddlewareMixin 在定義一箇中間件(類) 第3步在配置文件 配置 中間件有5個方法 process_request(self,request) process_view(self, request, view_func, view_args, view_kwargs) process_template_response(self,request,response) process_exception(self, request, exception) process_response(self, request, response)
實列ajax
在應用下鍵立一個文件夾(隨意取名字)在建立一個py文件 py文件下引入from django.utils.deprecation import MiddlewareMixin 定義一個類 配置文件配置 from django.utils.deprecation import MiddlewareMixin class MD1(MiddlewareMixin): #自定義中間件,不是必需要有下面這兩個方法,有request方法說明請求來了要處理,有response方法說明響應出去時須要處理,不是非要寫這兩個方法,若是你沒寫process_response方法,那麼會一層一層的往上找,哪一個中間件有process_response方法就將返回對象給哪一個中間件 def process_request(self, request): print("MD1裏面的 process_request") def process_response(self, request, response): print("MD1裏面的 process_response") return response
咱們給url 起一個別名· 之後無論url怎麼改 均可以實現原來的網址 就不會寫死了
url文件寫法 url(r'^index2/', views.index,name='cs'), 反向解析 後端views: from django.urls import reverse 能夠實現反向解析 reverse('別名') 例如:reverse('cs') 反向解析爲別名對應的地址 /index2/ 帶參數的反向解析: reverse( 'index' ,args=(10,))--- /index2/10/ html: {% url '別名' %} -- 例如:{% url 'cs' %} -- /index2/ 下面是代碼 實列 使其重定向至index別名對應的地址 /index2/10/ return redirect(everse( 'index' ,args=(10,)))
rurl文件寫法
from django.conf.urls import url from django.contrib import admin from app01 import views urlpatterns = [ url(r'^cs/', views.home,name='cs'), url(r'^cs1/', views.cs1,name='cs1'), ]
後端views.py
用於重定向 redirect 咱們利用別名 之後無論 別名cs1 對應的網址這麼變 咱們經過反解析 ,均可以找到他,寫活了他 from django.shortcuts import render,HttpResponse,redirect from django.urls import reverse def home(request): return redirect(reverse('cs1')) def cs1(request): return HttpResponse('測試')
建立應用python manage.py startapp
子應用名稱
在每app下傳建urls文件導入如下配置
from django.conf.urls import url from django.contrib import admin from app01 import views urlpatterns = [ url(r'^admin/', admin.site.urls), ]
主項目以下 配置 先導入include
from django.conf.urls import url,include from django.contrib import admin urlpatterns = [ url(r'^app01/', include('app01.urls',namespace='app01')), url(r'^app02/', include('app02.urls',namespace='app02')), ]
在路由分發中可能會錯亂爲了 避免 設置命名空間名稱namespace
from django.conf.urls import url,include from django.contrib import admin urlpatterns = [ # url(r'^admin/', admin.site.urls), url(r'^app01/', include('app01.urls',namespace='app01')), url(r'^app02/', include('app02.urls',namespace='app02')), ] 使用: 後端:reverse('命名空間名稱:別名') -- reverse('app01:home') hmtl:{% url '命名空間名稱:別名' %} -- {% url 'app01:home' %}
視圖是什麼? 視圖中的django中請求處理方式中CBV和FBV分別是什麼? 書寫一個FBV(函數類) 書寫一個CBV(對象) FBV(函數類) CBV(對象)加裝飾器? 請求相關:request 對象 方法 響應相關:HTTPResponse 對象 方法
一個視圖函數(類),簡稱視圖,是一個簡單的Python 函數(類),它接受Web請求而且返回Web響應 不管視圖自己包含什麼邏輯,都要返回響應。 約定成俗將視圖放置在項目(project)或應用程序(app)目錄中的名爲views.py的文件中
基於函數的view,就叫FBV 基於類的view,就叫CBV 書寫一個FBV(函數類) 書寫一個CBV(對象) 代碼以下
FBV(function base views) 就是在視圖裏使用函數處理請求。
from django.shortcuts import render,HttpResponse,redirect def cs(request): return redirect('/cs1/') #重定向 redirect(路徑)
CBV(class base views) 就是在視圖裏使用類處理請求。
最後一步源碼
http_method_names = ['get', 'post', 'put', 'patch', 'delete', 'head', 'options', 'trace'] def dispatch(self, request, *args, **kwargs): # Try to dispatch to the right method; if a method doesn't exist, # defer to the error handler. Also defer to the error handler if the # request method isn't on the approved list. if request.method.lower() in self.http_method_names:#實現分發的 handler = getattr(self, request.method.lower(), self.http_method_not_allowed) else: handler = self.http_method_not_allowed return handler(request, *args, **kwargs)
經過剖析源碼 咱們能夠在分發前執行咱們的邏輯
from django.views import View class LoginView(View): # def dispatch(self, request, *args, **kwargs): # print('xx請求來啦!!!!')請求來以前 但不知道是什麼方法前執行 # ret = super().dispatch(request, *args, **kwargs) # print('請求處理的邏輯已經結束啦!!!') # return ret def get(self,request): #處理get請求直接定義get方法,不須要本身判斷請求方法了,源碼中用dispatch方法中使用了反射來處理的 print('小小小小') return render(request,'login.html') def post(self,request): print(request.POST) return HttpResponse('登陸成功')
注意類請求 urls.py路由寫法
url(r'^路徑/', views.類名.as_view()), url(r'^login/', views.LoginView.as_view()),
FBV自己就是一個函數,因此和給普通的函數加裝飾器無差異 CBV(對象)加裝飾器須要先將其轉換爲方法裝飾器。Django中提供了method_decorator裝飾器用於將函數裝飾器轉換爲方法裝飾器。 代碼以下
FBV自己就是一個函數,因此和給普通的函數加裝飾器無差
def wrapper(func): def inner(*args, **kwargs): start_time = time.time() ret = func(*args, **kwargs) end_time = time.time() print("used:", end_time-start_time) return ret return inner # FBV版添加班級 @wrapper def add_class(request): if request.method == "POST": class_name = request.POST.get("class_name") models.Classes.objects.create(name=class_name) return redirect("/class_list/") return render(request, "add_class.html")
類中的方法與獨立函數不徹底相同,所以不能直接將函數裝飾器應用於類中的方法 ,咱們須要先將其轉換爲方法裝飾器。Django中提供了method_decorator裝飾器用於將函數裝飾器轉換爲方法裝飾器。
第一步先引入模塊from django.utils.decorators import method_decorator` 第2步 加語法糖@method_decorator(wrapper)` from django.shortcuts import render,HttpResponse from django.views import View from django.utils.decorators import method_decorator def wrapper(func): def inner(*args, **kwargs): print(11111) ret = func(*args, **kwargs) print(22222) return ret return inner # @method_decorator(wrapper,name='get') # 方式3給get加 用的很少 class LoginView(View): @method_decorator(wrapper) #方式1 def get(self,request): print('小小小小') return HttpResponse('登陸成功') def post(self,request): print(request.POST) return HttpResponse('登陸成功')
path_info 返回用戶訪問url,不包括域名 method 請求中使用的HTTP方法的字符串表示,全大寫表示。 GET 包含全部HTTP GET參數的類字典對象 POST 包含全部HTTP POST參數的類字典對象 body 請求體,byte類型 request.POST的數據就是從body裏面提取到的 request.method ——》 請求的方式 8種 GET POST PUT DELETE OPTIONS request.GET ——》 字典 url上攜帶的參數 request.POST ——》 字典 form表單經過POST請求提交的數據 request.path_info ——》 URL路徑 不帶參數 request.body ——》 請求體 request.FILES 上傳的文件 {} request.COOKIES cookie request.session session request.META 請求頭
from django.shortcuts import render,HttpResponse,redirect HTTPResponse('字符串') #返回字符串 render(request,'xx.html')#返回html頁面 redirect 重定向 def cs(request): return redirect('/cs1/') #重定向到url爲cs1的地址 def cs1(request): return HttpResponse('666') #返回字符串666 def cs1(request): render(request,'xx.html')#返回html頁面
什麼是ORM
1. MVC或者MVC框架中包括一個重要的部分,就是ORM,它實現了數據模型與數據庫的解耦,即數據模型的設計不須要依賴於特定的數據庫,經過簡單的配置就能夠輕鬆更換數據庫,這極大的方便了咱們開發 2. ORM 是「對象-關係-映射」的簡稱。類名對應表名 字段對應屬性 3. orm就是將類對象的語法翻譯成sql語句的一個引擎,
建立表3步曲
第1步 數據庫鏈接配置 第2步 models.py文件中建立一個類 也就是寫類的鍵表語句 第3步執行同步指令 使其類語句轉化爲數據庫可理解的語句
第1步鏈接數據庫前配置
settings配置文件中 本身先在數據庫中建立庫 DATABASES = { 'default': { 'ENGINE': 'django.db.backends.mysql', 'NAME': 'cs', 'USER':'root', 'PASSWORD':'123', 'HOST':'127.0.0.1', 'PORT':3306, } } 2 項目文件夾下的init文件中寫上下面內容,用pymysql替換mysqldb 由於django連接mysql默認使用的是mysqldb但其不支持py3.7因此不用 import pymysql pymysql.install_as_MySQLdb() settings配置文件中將 USE_TZ 的值改成 False # USE_TZ = True USE_TZ = False # 告訴mysql存儲時間時按照當地時間來寸,不要用utc時間 使用pycharm的數據庫客戶端的時候,時區問題要注意
第2步 建立一個類語句
models.py文件中建立一個類 同步指令會翻譯成mysql語句 UserInfo 是表名 models 固定寫法 models後面AutoField等是 字段 注意id字段不建立也能夠,系統會自動建立 括號裏面的primary_key等是 屬性 建立學生表實列 class UserInfo(models.Model): id = models.AutoField(primary_key=True) name = models.CharField(max_length=10) bday = models.DateField() checked = models.BooleanField()
第3步執行數據庫同步指令
第1種方式 在 Terminal中執行 python manage.py makemigrations #生成記錄,每次修改了models裏面的內容或者添加了新的app,新的app裏面寫了models裏面的內容,都要執行這兩條 python manage.py migrate #執行上面這個語句的記錄來建立表,生成的表名字前面會自帶應用的名字,例如:你的book表在mysql裏面叫作app01_book表 第2種方式 帶提示 tool---Run manage.py Task....或Ctrl+Alt+R 調出提示環境 執行 makemigrations 和 migrate 執行同步指令會在當前應用文件下下生成migrations文件夾 注意 每次修改了models裏面的內容或者添加了新的app,新的app裏面寫了models裏面的內容,都要執行這兩條 添加字段的時候別忘了,該字段不能爲空,全部要麼給默認值,要麼設置它容許爲空null=True
<1> CharField 字符串字段, 用於較短的字符串. CharField 要求必須有一個參數 maxlength, 用於從數據庫層和Django校驗層限制該字段所容許的最大字符數. <2> IntegerField #用於保存一個整數. <3> DecimalField 一個浮點數 小數字段. 必須 提供兩個參數: 參數 描述 max_digits 總位數(不包括小數點和符號) decimal_places 小數位數 舉例來講, 要保存最大值爲 999 (小數點後保存2位),你要這樣定義字段: models.DecimalField(..., max_digits=5, decimal_places=2) <4> AutoField 一個 IntegerField, 添加記錄時它會自動增加. 你一般不須要直接使用這個字段; 自定義一個主鍵:my_id=models.AutoField(primary_key=True) 若是你不指定主鍵的話,系統會自動添加一個主鍵字段到你的 model. <5> BooleanField bool字段 A true/false field. admin 用 checkbox 來表示此類字段. <6> TextField 一個容量很大的文本字段. admin 用一個 <textarea> (文本區域)表示該字段數據.(一個多行編輯框). <7> EmailField 一個帶有檢查Email合法性的 CharField,不接受 maxlength 參數. <8> DateField 一個日期字段. 共有下列額外的可選參數: Argument 描述 auto_now 當對象被保存時(更新或者添加都行),自動將該字段的值設置爲當前時間.一般用於表示 "last-modified" 時間戳. auto_now_add 當對象首次被建立時,自動將該字段的值設置爲當前時間.一般用於表示對象建立時間. (僅僅在admin中有意義...) <9> DateTimeField 通常用這個 一個日期時間字段. 相似 DateField 支持一樣的附加選項. <10> ImageField 圖片· 相似 FileField, 不過要校驗上傳對象是不是一個合法圖片.#它有兩個可選參數:height_field和width_field, 若是提供這兩個參數,則圖片將按提供的高度和寬度規格保存. <11> FileField 文件 一個文件上傳字段. 要求一個必須有的參數: upload_to, 一個用於保存上載文件的本地文件系統路徑. 這個路徑必須包含 strftime #formatting, 該格式將被上載文件的 date/time 替換(so that uploaded files don't fill up the given directory). admin 用一個<input type="file">部件表示該字段保存的數據(一個文件上傳部件) . 注意:在一個 model 中使用 FileField 或 ImageField 須要如下步驟: (1)在你的 settings 文件中, 定義一個完整路徑給 MEDIA_ROOT 以便讓 Django在此處保存上傳文件. (出於性能考慮,這些文件並不保存到數據庫.) 定義MEDIA_URL 做爲該目錄的公共 URL. 要確保該目錄對 WEB服務器用戶賬號是可寫的. (2) 在你的 model 中添加 FileField 或 ImageField, 並確保定義了 upload_to 選項,以告訴 Django 使用 MEDIA_ROOT 的哪一個子目錄保存上傳文件.你的數據庫中要保存的只是文件的路徑(相對於 MEDIA_ROOT). 出於習慣你必定很想使用 Django 提供的 get_<#fieldname>_url 函數.舉例來講,若是你的 ImageField 叫做 mug_shot, 你就能夠在模板中以 {{ object.#get_mug_shot_url }} 這樣的方式獲得圖像的絕對路徑. <12> URLField 用於保存 URL. 若 verify_exists 參數爲 True (默認), 給定的 URL 會預先檢查是否存在( 即URL是否被有效裝入且 沒有返回404響應). admin 用一個 <input type="text"> 文本框表示該字段保存的數據(一個單行編輯框) <13> NullBooleanField 相似 BooleanField, 不過容許 NULL 做爲其中一個選項. 推薦使用這個字段而不要用 BooleanField 加 null=True 選項 admin 用一個選擇框 <select> (三個可選擇的值: "Unknown", "Yes" 和 "No" ) 來表示這種字段數據. <14> SlugField "Slug" 是一個報紙術語. slug 是某個東西的小小標記(短籤), 只包含字母,數字,下劃線和連字符.#它們一般用於URLs 若你使用 Django 開發版本,你能夠指定 maxlength. 若 maxlength 未指定, Django 會使用默認長度: 50. #在 之前的 Django 版本,沒有任何辦法改變50 這個長度. 這暗示了 db_index=True. 它接受一個額外的參數: prepopulate_from, which is a list of fields from which to auto-#populate the slug, via JavaScript,in the object's admin form: models.SlugField (prepopulate_from=("pre_name", "name"))prepopulate_from 不接受 DateTimeFields. <13> XMLField 一個校驗值是否爲合法XML的 TextField,必須提供參數: schema_path, 它是一個用來校驗文本的 RelaxNG schema #的文件系統路徑. <14> FilePathField 可選項目爲某個特定目錄下的文件名. 支持三個特殊的參數, 其中第一個是必須提供的. 參數 描述 path 必需參數. 一個目錄的絕對文件系統路徑. FilePathField 據此獲得可選項目. Example: "/home/images". match 可選參數. 一個正則表達式, 做爲一個字符串, FilePathField 將使用它過濾文件名. 注意這個正則表達式只會應用到 base filename 而不是 路徑全名. Example: "foo.*\.txt^", 將匹配文件 foo23.txt 卻不匹配 bar.txt 或 foo23.gif. recursive可選參數.要麼 True 要麼 False. 默認值是 False. 是否包括 path 下面的所有子目錄. 這三個參數能夠同時使用. match 僅應用於 base filename, 而不是路徑全名. 那麼,這個例子: FilePathField(path="/home/images", match="foo.*", recursive=True) ...會匹配 /home/images/foo.gif 而不匹配 /home/images/foo/bar.gif <15> IPAddressField 一個字符串形式的 IP 地址, (i.e. "24.124.1.30"). <16> CommaSeparatedIntegerField 用於存放逗號分隔的整數值. 相似 CharField, 必需要有maxlength參數.
更多參數
1)null 若是爲True,Django 將用NULL 來在數據庫中存儲空值。 默認值是 False. (1)blank 若是爲True,該字段容許不填。默認爲False。 要注意,這與 null 不一樣。null純粹是數據庫範疇的,而 blank 是數據驗證範疇的。 若是一個字段的blank=True,表單的驗證將容許該字段是空值。若是字段的blank=False,該字段就是必填的。 (2)default 字段的默認值。能夠是一個值或者可調用對象。若是可調用 ,每有新對象被建立它都會被調用,若是你的字段沒有設置能夠爲空,那麼未來若是咱們後添加一個字段,這個字段就要給一個default值 (3)primary_key 若是爲True,那麼這個字段就是模型的主鍵。若是你沒有指定任何一個字段的primary_key=True, Django 就會自動添加一個IntegerField字段作爲主鍵,因此除非你想覆蓋默認的主鍵行爲, 不然不必設置任何一個字段的primary_key=True。 (4)unique 若是該值設置爲 True, 這個數據字段的值在整張表中必須是惟一的 (5)choices 由二元組組成的一個可迭代對象(例如,列表或元組),用來給字段提供選擇項。 若是設置了choices ,默認的表單將是一個選擇框而不是標準的文本框,<br>並且這個選擇框的選項就是choices 中的選項。 (6)db_index 若是db_index=True 則表明着爲此字段設置數據庫索引。 DatetimeField、DateField、TimeField這個三個時間字段,均可以設置以下屬性。 (7)auto_now_add 配置auto_now_add=True,建立數據記錄的時候會把當前時間添加到數據庫。 (8)auto_now 配置上auto_now=True,每次更新數據記錄的時候會更新該字段,標識這條記錄最後一次的修改時間。
2步曲
第1步引入對應的models.py文件 第2步 書寫添加數據語句 有2種方式
實列
第1種添加方式 from app01 import models def tj(request): new_obj = models.UserInfo( id=1, name='小白', bday='2019-09-27', # current_date checked=1, ) new_obj.save() # 翻譯成sql語句,而後調用pymysql,發送給服務端 print(new_obj)#UserInfo object 對象 print(new_obj.name) return HttpResponse('tj成功') 第2種添加方式 from app01 import models def tj(request): ret = models.UserInfo.objects.create( name='小白1', bday='2019-09-27', checked=0 ) print(ret)#UserInfo object 對象 print(ret.name) return HttpResponse('tj成功')
import datetime current_date = datetime.datetime.now() models.UserInfo.objects.create( name='楊澤濤2', bday='2019-09-27',# 直接插入時間沒有時區問題 cszhiduan=current_date,# 系統插入時間有時區問題current_date是當前時間 checked=0 ) 可是若是讓這個字段自動來插入時間,就會有時區的問題, auto_now_add可使建立記錄時自動添加當前建立記錄時的時間,存在時區問題 cszhiduan = models.DateTimeField(auto_now_add=True,null=True) 解決方法: settings配置文件中將USE_TZ的值改成False # USE_TZ = True USE_TZ = False # 告訴mysql存儲時間時按照當地時間來寸,不要用utc時間 使用pycharm的數據庫客戶端的時候,時區問題要注意
# bulk_create obj_list = [] for i in range(20): obj = models.Book( title=f'金瓶{i}', price=20+i, publish_date=f'2019-09-{i+1}', publish='24期出版社' ) obj_list.append(obj) models.Book.objects.bulk_create(obj_list) #批量建立 request.POST -- querydict類型 {'title': ['asdf '], 'price': ['212'], 'publish_date': ['2019-09-12'], 'publish': ['asdf ']} data = request.POST.dict() -- 可以將querydict轉換爲普通的python字典格式 建立數據 models.Book.objects.create( # title=title, # price=price, # publish_date=publish_date, # publish=publish **data )
在學查表前先搞清楚 queryset是查詢集是什麼?model對象是什麼? queryset是相似列表 裏面是model對象 queryset的方法model對象不必定能夠用 model對象能夠用點取值 而queryset不能夠
<1> all(): 查詢全部結果,結果是queryset類型 查詢全部的數據 .all方法 返回的是queryset集合 all_objs = models.Student.objects.all() # 相似於列表 -- queryset集合 for i in all_objs: print(i.name) print(all_objs) <2> filter(**kwargs): 它包含了與所給篩選條件相匹配的對象,結果也是queryset類型 Book.objects.filter(title='linux',price=100) #裏面的多個條件用逗號分開,而且這幾個條件必須都成立,是and的關係, models.Student.objects.all().filter(id=7) queryset類型能夠調用fitler在過濾 <3> get(**kwargs): 返回與所給篩選條件相匹配的對象,不是queryset類型,是行記錄對象,返回結果有且只有一個, 若是符合篩選條件的對象超過一個或者沒有都會拋出錯誤。捕獲異常try。 Book.objects.get(id=1) <4> exclude(**kwargs): 排除的意思,它包含了與所給篩選條件不匹配的對象,沒有不等於的操做昂,用這個exclude,返回值是queryset類型 Book.objects.exclude(id=6),返回id不等於6的全部的對象,或者在queryset基礎上調用,Book.objects.all().exclude(id=6) exclude(**kwargs): 排除,objects控制器和queryset集合均可以調用,返回結果是queryset類型 query = models.Student.objects.exclude(id=1) print(query) query = models.Student.objects.filter(age=38).exclude(id=6) print(query) <5> order_by(*field): 排序 queryset類型的數據來調用,對查詢結果排序,默認是按照id來升序排列的,返回值仍是queryset類型 models.Book.objects.all().order_by('price','id') #直接寫price,默認是按照price升序排列,按照字段降序排列,就寫個負號就好了order_by('-cs'),order_by('price','id')是多條件排序,按照price進行升序,price相同的數據,按照id進行升序 <6> reverse(): queryset類型的數據來調用,對查詢結果反向排序,返回值仍是queryset類型 # 只能夠排序以後反轉 # query = models.Student.objects.all().order_by('id').reverse() # print(query) <7> count(): queryset類型的數據來調用,返回數據庫中匹配查詢(QuerySet)的對象數量。 <8> first(): queryset類型的數據來調用 ,返回第一條記錄結果爲model對象類型 Book值 <9> last(): queryset類型的數據來調用,返回最後一條記錄,結果爲model對象類型 <10> exists(): queryset類型的數據來調用,若是QuerySet包含數據,就返回True,不然返回False 空的queryset類型數據也有布爾值True和False,可是通常不用它來判斷數據庫裏面是否是有數據,若是有大量的數據,你用它來判斷,那麼就須要查詢出全部的數據,效率太差了,用count或者exits 例:all_books = models.Book.objects.all().exists() #翻譯成的sql是SELECT (1) AS `a` FROM `app01_book` LIMIT 1,就是經過limit 1,取一條來看看是否是有數據 <11> values(*field): 用的比較多,queryset類型的數據來調用,返回一個ValueQuerySet——一個特殊的QuerySet,運行後獲得的並非一系列 model的實例化對象,而是一個可迭代的字典序列,只要是返回的queryset類型,就能夠繼續鏈式調用queryset類型的其餘的查找方法,其餘方法也是同樣的。 裏面能夠加子段顯示 <12> values_list(*field): 它與values()很是類似,它返回的是一個元組序列,values返回的是一個字典序列 裏面能夠加子段顯示 <13> distinct(): values和values_list獲得的queryset類型的數據來調用,從返回結果中剔除重複紀錄 去重,結果仍是queryset 裏面不能夠傳參 顯示nanme等等能夠用來去重 query = models.Student.objects.all().values('age').distinct() print(query)
Book.objects.filter(price__in=[100,200,300]) #price值等於這三個裏面的任意一個的對象 Book.objects.filter(price__gt=100) #大於,大於等因而price__gte=100,別寫price>100,這種參數不支持 Book.objects.filter(price__lt=100) 小於 Book.objects.filter(price__range=[100,200]) #sql的between and,大於等於100,小於等於200 Book.objects.filter(title__contains="python") #title值中包含python的 Book.objects.filter(title__icontains="python") #不區分大小寫 Book.objects.filter(title__startswith="py") #以什麼開頭,istartswith 不區分大小寫 Book.objects.filter(pub_date__year=2012) date類型 實列 # all_books = models.Book.objects.filter(pub_date__year=2012) #找2012年的全部書籍 # all_books = models.Book.objects.filter(pub_date__year__gt=2012)#找大於2012年的全部書籍 all_books = models.Book.objects.filter(pub_date__year=2019,pub_date__month=2)#找2019年月份的全部書籍,若是明明有結果,你卻查不出結果,是由於mysql數據庫的時區和我們django的時區不一樣致使的,瞭解一下就好了,你須要作的就是將django中的settings配置文件裏面的USE_TZ = True改成False,就能夠查到結果了,之後這個值就改成False,並且就是由於我們用的mysql數據庫纔會有這個問題,其餘數據庫沒有這個問題。
簡單查詢:filter() -- 結果是queryset類型的數據裏面是一個個的model對象,相似於列表 models.UserInfo.objects.filter(id=7).delete() #queryset對象調用 models.UserInfo.objects.filter(id=7)[0].delete() #model對象調用
方式1:update models.UserInfo.objects.filter(id=2).update( name='籃子文', checked = 0, ) #錯誤示例,model對象不能調用update方法 models.UserInfo.objects.filter(id=2)[0].update( name='加籃子+2', # checked = 0, ) 方式2 ret = models.UserInfo.objects.filter(id=2)[0] ret.name = '加籃子+2' ret.checked = 1 ret.save() 更新時的auto_now參數 # 更新記錄時,自動更新時間,建立新紀錄時也會幫你自動添加建立時的時間,可是在更新時只有使用save方法的方式2的形式更新才能自動更新時間,有缺陷,放棄 now2 = models.DateTimeField(auto_now=True,null=True)
爲何要在類模型定義__str__
方法?
爲了便於觀察 打印一個對象,讓他顯示一個可以看懂的值,__str__,當print()打印實例化對象時會調用__str__() from django.db import models class Book(models.Model): id = models.AutoField(primary_key=True) title = models.CharField(max_length=32) price = models.DecimalField(max_digits=8,decimal_places=2,) pub_date = models.DateTimeField() #必須存這種格式"2012-12-12" publish = models.CharField(max_length=32) def __str__(self): #後添加這個str方法,也不須要從新執行同步數據庫的指令 return self.title #當咱們打印這個類的對象的時候,顯示title值
圖書管理系統 實現對書籍的查看 新增 刪除 內容和樣式以下: 查看頁面
解題思路
查看功能的實現 建立一張表 裏面有 id 名稱 價格 日期 出版社 字段 html 寫頁面記得 配置靜態文件 利用orm .all得到查詢集和 傳給前端 前端 for 模板渲染 STATIC_URL = '/static/' #靜態文件路徑別名 STATICFILES_DIRS = [ os.path.join(BASE_DIR, '項目下建立的文件夾名'),第2個參數建立的文件夾名 ] <link rel="stylesheet" href="/別名/bootstrap-3.3.7-dist/css/bootstrap.min.css"> def showbooks(request): if request.method == 'GET': books=models.Boo.objects.all() print(books) return render(request,'showbooks.html',{'books':books}) <!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>Title</title> <link rel="stylesheet" href="/static/bootstrap-3.3.7-dist/css/bootstrap.min.css"> </head> <body> <h1>查看書籍</h1> <div class="container"> <div class="row"> <div class="col-md-8 col-md-offset-2"> <a href="/add_book/" class="btn btn-primary">添加書籍</a> <table class="table table-striped table-hover"> <thead> <tr> <th>編號</th> <th>書籍名稱</th> <th>價格</th> <th>出版日期</th> <th>出版社</th> <th>操做</th> </tr> </thead> <tbody> {% for book in books %} <tr> <td>{{ forloop.counter }}</td> <td>{{ book.title }}</td> <td>{{ book.price }}</td> <td>{{ book.c_date|date:'Y-m-d' }}</td> <td>{{ book.press }}</td> <td> <a href="" class="btn btn-warning">編輯</a> <a href="" class="btn btn-danger">刪除</a> </td> </tr> {% endfor %} </tbody> </table> </div> </div> </div> </body> </html>
添加功能的實現 點擊a標籤 跳轉頁面(注意不用別名 要加/) <a href="/add_book/" class="btn btn-primary">添加書籍</a> input標籤name值最好設置與表字段相同 返回查看頁面 要用重定向 否則不走url分發 orm取不到數據庫數據 return render(request,'showbooks.html') def add_book(request): if request.method == 'GET': return render(request,'add_book.html') else: ret = request.POST.dict() ret.pop('csrfmiddlewaretoken') print() models.Boo.objects.create( **(ret) ) return render(request,'showbooks.html') <!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>Title</title> <link rel="stylesheet" href="/static/bootstrap-3.3.7-dist/css/bootstrap.min.css"> </head> <body> <h1>添加書籍</h1> <div class="container"> <div class="row"> <div class="col-md-8 col-md-offset-2"> <form action="" method="post"> {% csrf_token %} <div class="form-group"> <label for="title">書籍名稱</label>{# "for" 屬性的值設置爲相關元素的 id 屬性的值。#} <input type="text" class="form-control" id="title" placeholder="title" name="name"> </div> <div class="form-group"> <label for="price">價格</label> <input type="number" class="form-control" id="price" placeholder="price" name="price"> </div> <div class="form-group"> <label for="publish_date">出版日期</label> <input type="date" class="form-control" id="publish_date" placeholder="publish_date" name="c_date"> </div> <div class="form-group"> <label for="publish">出版社</label> <input type="text" class="form-control" id="publish" placeholder="publish" name="press"> </div> <button type="submit" class="btn btn-success pull-right">提交</button> </form> </div> </div> </div> </body> </html>
刪除功能的實現
<a href="{% url 'delete_book' book.pk %}" class="btn btn-danger">刪除</a> 對象.pk 就是獨一無2的 models.Book.objects.filter(id=n).delete()
編輯功能的實現
點擊編輯按鈕pk傳過去 獲取到對象 對象傳過去 修改values值 注意時間 {{ book_obj.publish_date|date:'Y-m-d' }} <a href="{% url 'edit_book' book.pk %}" class="btn btn-warning">編輯</a> def edit_book(request,n): book_obj = models.Book.objects.filter(pk=n) if request.method == 'GET': return render(request,'edit_book.html',{'book_obj':book_obj.first()}) else: print(request.POST) # <QueryDict: {'title': ['金瓶7777'], 'price': ['27.00'], 'publish_date': ['2019-09-08'], 'publish': ['24期出版社xx']}> ret = request.POST.dict() book_obj.update( **ret ) return redirect('showbooks') <!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>Title</title> <link rel="stylesheet" href="/static/bootstrap-3.3.7-dist/css/bootstrap.min.css"> </head> <body> <h1>編輯書籍</h1> <div class="container"> <div class="row"> <div class="col-md-8 col-md-offset-2"> <form action="" method="post"> <div class="form-group"> <label for="title">書籍名稱</label> <input type="text" class="form-control" id="title" placeholder="title" name="title" value="{{ book_obj.title }}"> </div> <div class="form-group"> <label for="price">價格</label> <input type="number" class="form-control" id="price" placeholder="price" name="price" value="{{ book_obj.price }}"> </div> <div class="form-group"> <label for="publish_date">出版日期</label> <input type="date" class="form-control" id="publish_date" placeholder="publish_date" name="publish_date" value="{{ book_obj.publish_date|date:'Y-m-d' }}"> </div> <div class="form-group"> <label for="publish">出版社</label> <input type="text" class="form-control" id="publish" placeholder="publish" name="publish" value="{{ book_obj.publish }}"> </div> <button type="submit" class="btn btn-success pull-right">提交</button> </form> </div> </div> </div> </body> </html>
建立表代碼
from django.db import models class Author(models.Model): """ 做者表 """ name=models.CharField( max_length=32) age=models.IntegerField() # authorDetail=models.OneToOneField(to="AuthorDetail",to_field="nid",on_delete=models.CASCADE) au=models.OneToOneField("AuthorDetail",on_delete=models.CASCADE) def __str__(self): return self.name class AuthorDetail(models.Model): """ 做者詳細信息表 """ birthday=models.DateField() telephone=models.CharField(max_length=11) addr=models.CharField(max_length=64) # class Meta: # db_table='authordetail' #指定表名 # ordering = ['-id',] def __str__(self): return self.telephone + self.addr class Publish(models.Model): """ 出版社表 """ name=models.CharField( max_length=32) city=models.CharField( max_length=32) def __str__(self): return self.name class Book(models.Model): """ 書籍表 """ title = models.CharField( max_length=32) publishDate=models.DateField() price=models.DecimalField(max_digits=5,decimal_places=2) publishs=models.ForeignKey(to="Publish",on_delete=models.CASCADE,) authors=models.ManyToManyField('Author',) def __str__(self): return self.title
多表增長 有2種方式 一種是直接利用字段增長 一種是利用找到的mode對象增長 下面是 代碼示例 一對一 和 一對多 方法相同
一對一 和 一對多
第一種方式 利用新生成的字段增長 models.Author.objects.create( name='海狗', age=59, au_id=4 ) 第2種方式(與id爲4的就是一對一關係)ghj au_obj = models.AuthorDetail.objects.get(id=4) 第一種方式 models.Author.objects.create( name='海狗', age=59, au=au_obj ) 一對多 pub_obj = models.Publish.objects.get(id=3) models.Book.objects.create( title='xx2', price=13, publishDate='2011-11-12', # publishs=pub_obj , #類屬性做爲關鍵字時,值爲model對象 publishs_id=3 # 若是關鍵字爲數據庫字段名稱,那麼值爲關聯數據的值 )
多對多
第一種 new_obj = models.Book.objects.create( title='海狗產後護理第二部', price=0.5, publishDate='2019-09-29', publishs_id=2, ) new_obj.authors.add(3, 5) # #*args **kwargs new_obj.authors.add(*[3, 5]) # 用的最多, 第2種 ziwen = models.Author.objects.get(id=3) haigou = models.Author.objects.get(id=5) new_obj = models.Book.objects.create( title='海狗產後護理第二部', price=0.5, publishDate='2019-09-29', publishs_id=2, ) new_obj.authors.add(ziwen, haigou)
一對一 一對多 刪除都是找到mode對象delete()就行 多對多就比較特殊 要先找到對象 在點屬性 進行修改
一對一 # models.AuthorDetail.objects.filter(id=3).delete() 一對多 models.Publish.objects.filter(id=3).delete() # 多對多 book_obj = models.Book.objects.get(id=2) book_obj.authors.clear() # 清除 book_obj.authors.set(['1','5']) # 先清除再添加,至關於修改
找到對象直接改 第一種 models.Book.objects.filter(id=5).update( title='華麗麗', publishs=ret, publishs_id=1, ) 第2種 ret = models.Publish.objects.get(id=2) models.Book.objects.filter(id=5).update( title='華麗麗', publishs=ret, )
查詢2種方式 (正向查詢,反向查詢) 關係屬性寫在表1,關聯到表2,那麼經過表1的數據去找表2的數據,叫作正向查詢,返過來就是反向查詢 正向查詢用 屬性 反向查詢用 表名(小寫的) 注意 多對多 反向查詢用 表名_set 只要含義多個的可能性都用all所有查詢出來 在for循環 獲得信息 下面是查詢實列
查詢實列
# 查詢 # 一對一 # 關係屬性寫在表1,關聯到表2,那麼經過表1的數據去找表2的數據,叫作正向查詢,返過來就是反向查詢 # 查詢一下王洋的電話號碼 # 正向查詢 對象.屬性 # obj = models.Author.objects.filter(name='王洋').first() # ph = obj.au.telephone # print(ph) # 查一下電話號碼爲120的做者姓名 # 反向查詢 對象.小寫的表名 # obj = models.AuthorDetail.objects.filter(telephone=120).first() # ret = obj.author.name #陳碩 # print(ret) # 一對多 # 查詢一下 海狗的慫逼人生這本書是哪一個出版社出版的 正向查詢 # obj = models.Book.objects.filter(title='海狗的慫逼人生').first() # ret = obj.publishs.name # print(ret) #24期出版社 # 查詢一下 24期出版社出版過哪些書 # obj = models.Publish.objects.filter(name='24期出版社').first() # # ret = obj.book_set.all() #<QuerySet [<Book: 母豬的產後護理>, <Book: 海狗的慫逼人生>]> # for i in ret: # print(i.title) # 多對多 # 海狗的慫逼人生 是哪些做者寫的 -- 正向查詢 # obj = models.Book.objects.filter(title='海狗的慫逼人生').first() # ret = obj.authors.all() # # print(ret) #<QuerySet [<Author: 王洋>, <Author: 海狗>]> # for i in ret: # print(i.name) # 查詢一下海狗寫了哪些書 -- 反向查詢 # obj = models.Author.objects.filter(name='海狗').first() # ret = obj.book_set.all() # print(ret) # for i in ret: # print(i.publishs.name) # print(i.title) # return HttpResponse('ok')
模板渲染的官方文檔 https://docs.djangoproject.com/en/1.11/ref/templates/builtins/#std:templatetag-for 變量相關的用{{}},邏輯相關的用{% %}。
咱們能夠利用 深度查詢據點符(.)進行查詢 <h2>{{ 變量 }}</h2> <h2>{{ 字典.items }}</h2>items keys vlues <h2>我是"{{ 列表.1 }}"</h2> <h2>{{ 對象.對象方法 }}</h2> #若是調用的方法須要傳參,sorry用不了 代碼示例以下
views.py視圖函數中寫法
from django.shortcuts import render def home(request): import datetime current_time = datetime.datetime.now() name = '小白' num = 101 d1 = {'xx':'oo','xx2':'oo2','xx3':[11,22,33]} d2 = ['11','22','33'] d3 = [] l1 = ['李業','陳碩','王洋','海狗'] class Person: n = '類的屬性' def p(self): return '類p的返回值' obj = Person() return render(request,'home.html',{'name':name,'d1':d1})
HTML頁面寫法
注意字典 列表 和對象中方法 <h2>{{ name }}</h2> <h2>{{ d1.items }}</h2>items keys vlues <h2>我是"{{ l1.1 }}"</h2> <h2>{{ num }}</h2> <h2>{{ obj.p }}</h2> #若是調用的方法須要傳參,sorry用不了
過濾器的語法: {{ value|filter_name:參數 }} 使用管道符"|"來應用過濾器。 注意事項: 過濾器支持「鏈式」操做。即一個過濾器的輸出做爲另外一個過濾器的輸入。 過濾器能夠接受參數,例如:{{ sss|truncatewords:30 }},這將顯示sss的前30個詞。 過濾器參數包含空格的話,必須用引號包裹起來。好比使用逗號和空格去鏈接一個列表中的元素,如:{{ list|join:', ' }} '|'左右沒有空格沒有空格沒有空格 參考博客:https://www.cnblogs.com/clschao/articles/10414811.html 代碼示例
default,length,filesizeformat,slice-------等
default 若是一個變量是false或者爲空,使用給定的默認值。 不然,使用變量的值。 {{ value|default:"nothing"}} 若是value沒有傳值或者值爲空的話就顯示nothing length返回值的長度,做用於字符串和列表。 {{ value|length }} 返回value的長度,如 value=['a', 'b', 'c', 'd']的話,就顯示4. filesizeformat將值格式化爲一個 「人類可讀的」 文件尺寸 (例如 '13 KB', '4.1 MB', '102 bytes', 等等)。 {{ value|filesizeformat }} 若是 value 是 123456789,輸出將會是 117.7 MB。 slice 切片,若是 value="hello world",還有其餘可切片的數據類型 {{value|slice:"2:-1"}} date格式化, value=datetime.datetime.now() {{ value|date:"Y-m-d H:i:s"}} 關於時間日期的可用的參數(除了Y,m,d等等)還有不少,有興趣的能夠去查查看看。 safe {{ value|safe}} 若是value = "<a href='#'>點我</a>" 那麼頁面顯示的是a標籤 truncatechars若是字符串字符多於指定的字符數量,那麼會被截斷。截斷的字符串將以可翻譯的省略號序列(「...」)結尾。 {{ value|truncatechars:9}} #注意:最後那三個省略號也是9個字符裏面的,也就是這個9截斷出來的是6個字符+3個省略號,有人會說,怎麼展開啊,配合前端的點擊事件就行啦 truncatewords在必定數量的字後截斷字符串,是截多少個單詞。 例如:‘hello girl hi baby yue ma’, {{ value|truncatewords:3}} #上面例子獲得的結果是 'hello girl h1...' cut移除value中全部的與給出的變量相同的字符串 {{ value|cut:' ' }} 若是value爲'i love you',那麼將輸出'iloveyou'. join使用字符串鏈接列表,{{ list|join:', ' }},就像Python的str.join(list)
格式 以下 {% tag %} 標籤 內容 ... {% endtag %} forloop---模板變量 for標籤----連續生成標籤 for ... empty---爲空在生成
for標籤
生成幾個p標籤 {% for person in person_list %} <p>{{ person.name }}</p> <!--凡是變量都要用兩個大括號括起來--> {% endfor %}
反向循環
{% for obj in list reversed %}
遍歷一個字典:
{% for key,val in dic.items %} <p>{{ key }}:{{ val }}</p> {% endfor %}
forloop(模板變量)
forloop.counter 當前循環的索引值(從1開始),forloop是循環器,經過點來使用功能 forloop.counter0 當前循環的索引值(從0開始) forloop.revcounter 當前循環的倒序索引值(從1開始) forloop.revcounter0 當前循環的倒序索引值(從0開始) forloop.first 當前循環是否是第一次循環(布爾值) forloop.last 當前循環是否是最後一次循環(布爾值) forloop.parentloop 本層循環的外層循環的對象,再經過上面的幾個屬性來顯示外層循環的計數等 實列 {% for i in d2 %} {% for k,v in d1.items %} <li>{{ forloop.counter }}-- {{ forloop.parentloop.counter }} === {{ k }} -- {{ v }}</li> {% endfor %} {% endfor %}
for ... empty
for
標籤帶有一個可選的{% empty %}
從句,經過它咱們能夠定義當列表爲空時的輸出內容
{% for person in person_list %} <p>{{ person.name }}</p> {% empty %} <p>你找的東西沒有</p> {% endfor %}
if 標籤
{% if %}
會對一個變量求值,若是它的值是「True」(存在、不爲空、且不是boolean類型的false值),對應的內容塊會輸出。
{% if num > 100 or num < 0 %} <p>無效</p> <!--不知足條件,不會生成這個標籤--> {% elif num > 80 and num < 100 %} <p>優秀</p> {% else %} <!--也是在if標籤結構裏面的--> <p>湊活吧</p> {% endif %} if語句支持 and 、or、==、>、<、!=、<=、>=、in、not in、is、is not判斷,注意條件兩邊都有空格。
with(起別名)
方法1 {% with total=business.employees.count %} #注意等號兩邊不能有空格 {{ total }} <!--只能在with語句體內用--> {% endwith %} 方法2 {% with business.employees.count as total %} {{ total }} {% endwith %}
在寫html頁面中 發現有不少頁面有雷同的樣式 爲了避免必重複造輪子
Web框架須要一種很便利的方法用於動態生成HTML頁面。 最多見的作法是使用模板。
模板包含所需HTML頁面的靜態部分,以及一些特殊的模版語法,用於將動態內容插入靜態部分。
模板的設計實現了業務邏輯view與顯示內容template的分離,一個視圖可使用任意一個模板,一個模板能夠供多個視圖使用。
1. 建立一個base.html頁面(做爲母版,其餘頁面來繼承它使用 名字隨便取) 2. 在母版中定義block塊(能夠定義多個,整個頁面任意位置) {% block content %} <!-- 預留的鉤子,共其餘須要繼承它的html,自定義本身的內容content --> {% endblock %} 3 其餘頁面繼承寫法 {% extends 'base.html' %} 必須放在頁面開頭 4 頁面中寫和母版中名字相同的block塊,從而來顯示自定義的內容 {% block content %} <!-- 預留的鉤子,共其餘須要繼承它的html,自定義本身的內容 --> {{ block.super }} #這是顯示繼承的母版中的content這個快中的內容 這是xx1 {% endblock %} 如下是具體運行代碼
第一步建立一個母模板
在templates文件夾 中建立一個muban.html
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>模板</title> <style> {% block css %} #mub{ width: 100%; height: 50px; background-color: cornflowerblue; } {% endblock %}{#預留的鉤子,共其餘須要繼承它的html,自定義本身的內容#} </style> </head> <body> <div id="mub">我是模板</div> {% block content %} <!-- 預留的鉤子,共其餘須要繼承它的html,自定義本身的內容 --> <h1>我是模板h1</h1> {% endblock %} {% block cs2 %} <!-- 預留的鉤子,共其餘須要繼承它的html,自定義本身的內容 --> <h1>我是測試2</h1> {% endblock %} </body> </html>
第2步其餘頁面繼承寫法
在templates文件夾 中建立一個home.html 繼承於muban.html
{% extends 'muban.html' %} {% block css %} #mub{ width: 100%; height: 50px; background-color: red; } #s6{ width: 50%; height: 50px; background-color: red; float: right; } {% endblock %} {% block content %} <!-- 預留的鉤子,共其餘須要繼承它的html,自定義本身的內容 --> <h1>我改變了模板的內容</h1> <div id="s6">我來測試</div> {% endblock %} {% block cs2 %} <!-- 預留的鉤子,共其餘須要繼承它的html,自定義本身的內容 --> {{ block.super }} 我在測試2下面 {% endblock %}
組件就是相似於python中的模塊 何時用 何時導入 好比常見的導航條,頁尾信息等組件 咱們通常 保存在單獨的文件中, 組件封裝了功能不能夠改 模板能夠修改
分頁器的使用 Form modelForm orm cookie和session 中間件 信號 具體介紹 https://www.cnblogs.com/tianshuai1/p/11042166.html
1 在templates文件中建立html頁面,裏面寫上本身封裝的組件內容,xx.html 2 新的html頁面使用這個組件 {% include 'xx.html' %}#include固定寫法 xx.html引用的組件名 如下是代碼 注意 先加載組件後 渲染
建立組件
在templates文件夾 中建立一個組件 title.html
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>Title</title> <style> .nav{ background-color: pink; height: 40px; } </style> </head> <body> <div class="nav"> <span>我的中心</span> <span>首頁</span> <span>註冊</span> <span>登陸</span> </div> </body> </html>
引用組件
在templates文件夾 中建立一個home.html 引用組件 title.html
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>Title</title> </head> <body> {% include 'title.html' %} <h1>這是新項目首頁</h1> </body> </html>
爲何要有自定義標籤和過濾器?
由於在現實編程中可能內置的標籤過濾器 不能夠知足咱們的需求 全部須要咱們本身來建立
1 在應用下建立一個叫作templatetags的文件夾(名稱不能改),在裏面建立一個py文件,例如xx.py 2 在xx.py文件中引用django提供的template類,寫法 from django import template register = template.Library() #register變量名稱不能改 # 自定義標籤 沒有參數個數限制 from django import template register = template.Library() #register變量名稱不能改 @register.filter #參數至多兩個 也就是管道後最多隻有一個 def guolv(v1,v2): """ :param v1: 變量的值 管道前面的 :param v2: 傳的參數 管道後面的,若是不須要傳參,就不要添加這個參數 :return: """ return v1+v2 使用: {% load xx %} xx是py文件 先在HTML頁面引入 {{ name|guolv:'oo' }} 使用過濾器 guolv是本身定義的過濾器函數名 下面是執行的代碼
4.7.2.1在應用文件夾下 建立templatetags文件夾並在裏面建立一個xx.文件
from django import template register = template.Library() #register變量名稱不能改 @register.filter #參數至多兩個 def guolv(v1,v2): """ :param v1: 變量的值 管道前面的 :param v2: 傳的參數 管道後面的,若是不須要傳參,就不要添加這個參數 :return: """ return v1+v2
4.7.2.2視圖views中代碼
from django.shortcuts import render,HttpResponse name='測試+' def home(request): return render(request,'home.html',{'name':name})
4.7.2.3建立要引用自定義過濾器的html頁面
{% load xx %}{#xx是templatetags文件夾下的xx.py文件#} <!doctype html> <html lang="en"> <head> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, user-scalable=no, initial-scale=1.0, maximum-scale=1.0, minimum-scale=1.0"> <meta http-equiv="X-UA-Compatible" content="ie=edge"> <title>Document</title> </head> <body> {{ name|guolv:'要傳給n2的參數' }} </body> </html>
inclusion_tag在使用的時候能夠幫咱們減小不少前端和後端重複的代碼
多用於返回html代碼片斷 原理先運行nue.html 調用xx.py 中res函數 res函數將返回值給@register.inclusion_tag對應的頁面('result.html') 模板渲染後 以組件的形式給原來的nue.htm
**小列題 **
利用組件 利用後端傳來的數據['c1','c2','c3'] 要求組件 後端不能夠修改 利用 inclusion_tag 來實現 實現流程 templatetags文件夾名 應用下建立 固定寫法
home.html
{% load xx %}#xx是templatetags文件夾中本身定義的xx.py文件 <!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>Title</title> </head> <body> {% inclusion li %} #inclusion是xx.py文件中本身定義的函數 #li是參數 後端傳過來的 列如傳來的是['c1','c2','c3'] </body> </html>
zujian.html組鍵
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>Title</title> <style> .a{ width: 40px; height: 40px; } </style> </head> <body> <ul> {% for i in li %} <li class="a" >{{ i }}</li> {% endfor %} </ul> </body> </html>
xx.py
# inclusion_tag 返回html片斷的標籤 from django import template register = template.Library() @register.inclusion_tag('zujian.html') # 括號是組件 def inclusion(li): # li 是後端傳過來的['c1','c2','c3'] l2 = [] for i in li: l2.append(i + 'a') return {'li': l2}#返回必定是字典 鍵名要與組件有聯繫
js、css、img等都叫作靜態文件,那麼關於django中靜態文件的配置,咱們就須要在settings配置文件裏面寫上這寫內容: 目錄:別名也是一種安全機制,瀏覽器上經過調試臺你可以看到的是別名的名字,這樣別人就不能知道你靜態文件夾的名字了,否則別人就能經過這個文件夾路徑進行攻擊。
1 項目目錄下建立一個文件夾,例如名爲 static_file,將全部靜態文件放到這個文件夾中 2 settings 配置文件中進行下面的配置 # 靜態文件相關配置 STATIC_URL = '/static/' #靜態文件路徑別名 STATICFILES_DIRS = [ os.path.join(BASE_DIR, 'static_file'),第2個參數建立的文件夾名 ] 3 html中引入 引入<link rel="stylesheet" href="/abc/css/index.css"> 第2種 1 項目目錄下建立一個文件夾,例如名爲 static_file,將全部靜態文件放到這個文件夾中 2 settings 配置文件中進行下面的配置 # 靜態文件相關配置 STATIC_URL = '/static/' #靜態文件路徑別名 STATICFILES_DIRS = [ os.path.join(BASE_DIR, 'static_file'),第2個參數建立的文件夾名 ] html文件開頭加上 {% load static %} 固定寫法 <link rel="stylesheet" href="{% static 'sw/sweetalert.css' %}"> static是固定寫法
第一項目目錄下建立一個文件夾,例如名爲static_file,將全部靜態文件放到這個文件夾中
第2找到settings 配置文件中進行下面的配置
STATIC_URL = '/abc/' #靜態文件路徑別名 能夠隨便改 #注意第2個參數必定對應建立的文件夾名 別名能夠隨便改 STATICFILES_DIRS = [ os.path.join(BASE_DIR, 'static_file'), ]
第3引入的配置文件的html頁面內容
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>Title</title> <link rel="stylesheet" href="/abc/css/index.css"> <link rel="stylesheet" href="/abc/plugins/bootstrap-3.3.7-dist/css/bootstrap.min.css"> </head> <body> <input type="text" class="form-control"> <h1>紅浪漫spa會所</h1> <img src="/abc/img/timg.jpg" alt=""> <a href="{% url 'home' %}">首頁</a> 技師: <ul> <li>小白</li> <li>小黑</li> </ul> </body> </html>
咱們給url 起一個別名· 之後無論url怎麼改 均可以實現原來的網址 就不會寫死了
rurl文件寫法 url(r'^index2/', views.index,name='cs'), 反向解析 後端views: from django.urls import reverse 能夠實現反向解析 reverse('別名') 例如:reverse('cs') 反向解析爲別名對應的地址 /index2/ 帶參數的反向解析: reverse( 'index' ,args=(10,))--- /index2/10/ html: {% url '別名' %} -- 例如:{% url 'cs' %} -- /index2/ 下面是代碼 實列 使其重定向至index別名對應的地址 /index2/10/ return redirect(everse( 'index' ,args=(10,)))
rurl文件寫法
from django.conf.urls import url from django.contrib import admin from app01 import views urlpatterns = [ url(r'^cs/', views.home,name='cs'), url(r'^cs1/', views.cs1,name='cs1'), ]
後端views.py
用於重定向 redirect 咱們利用別名 之後無論 別名cs1 對應的網址這麼變 咱們經過反解析 ,均可以找到他,寫活了他 from django.shortcuts import render,HttpResponse,redirect from django.urls import reverse def home(request): return redirect(reverse('cs1')) def cs1(request): return HttpResponse('測試')
建立應用python manage.py startapp
子應用名稱
在每app下傳建urls文件導入如下配置
from django.conf.urls import url from django.contrib import admin from app01 import views urlpatterns = [ url(r'^admin/', admin.site.urls), ]
主項目以下 配置 先導入include
from django.conf.urls import url,include from django.contrib import admin urlpatterns = [ url(r'^app01/', include('app01.urls',namespace='app01')), url(r'^app02/', include('app02.urls',namespace='app02')), ]
在路由分發中可能會錯亂爲了 避免 設置命名空間名稱namespace
from django.conf.urls import url,include from django.contrib import admin urlpatterns = [ # url(r'^admin/', admin.site.urls), url(r'^app01/', include('app01.urls',namespace='app01')), url(r'^app02/', include('app02.urls',namespace='app02')), ] 使用: 後端:reverse('命名空間名稱:別名') -- reverse('app01:home') hmtl:{% url '命名空間名稱:別名' %} -- {% url 'app01:home' %}
AJAX是一種客戶端Web開發技術 特色是異步請求,局部刷新;這一特色給用戶的感覺是在不知不覺中完成請求和響應過程
先引入jquery 第一步綁定事件 第2步利用jquery獲取用戶內容 第3步 利用ajax 義字典形式數據提交到url對應的地址 進行路由匹配,執行相應的視圖函數 返會邏輯結果 第4步ajax中success鍵對應的匿名函數 形參res接受到,以前視圖函數的返回值 進行匿名函數邏輯判斷 好比利用js添加內容等等
{% csrf_token %}---必加安全驗證 用戶名: <input type="text" id="username"> 密碼: <input type="password" id="password"> <button id="sub">提交</button> <span class="error"></span> <script src="{% static 'js/jquery.js' %}"></script> <script src="{% static 'js/jquery.cookie.js' %}"></script> $('#sub').click(function () { var uname = $('#username').val(); var pwd = $('#password').val(); var csrf = $('[name=csrfmiddlewaretoken]').val(); ---固定寫法得到隨機值 $.ajax({ url:'{% url "login" %}', type:'post', data:{username:uname,password:pwd,csrfmiddlewaretoken:csrf},--發送給後端 success:function (res) {---ret是後端給的 if (res === '1'){ location.href = '/home/'; // 重定向http://127.0.0.1:8000/home/ }else{ $('.error').text('用戶名密碼錯誤!'); } } }) })
搜索引擎根據用戶輸入的關鍵字,自動提示檢索關鍵字。 還有一個很重要的應用場景就是註冊時候的用戶名的查重。
安全認證機制CSRF是什麼? django中的安全認證機制CSRF? 如何解決django中CSRF?
詳述CSRF(Cross-site request forgery),中文名稱:跨站請求僞造,也被稱爲:one click attack/session riding,縮寫爲:CSRF/XSRF。攻擊者經過HTTP請求江數據傳送到服務器,從而盜取回話的cookie。盜取回話cookie以後,攻擊者不只能夠獲取用戶的信息,還能夠修改該cookie關聯的帳戶信息。
django項目中默認對POST請求進行了csrf認證,只須要在模板提交數據的代碼塊中加入模板標籤{{% vsrf_token %}}便可,(不須要註銷seetings.py配置文件MIDDLEWARE列表中的'django.middleware.csrf.CsrfViewMiddleware',),模板頁面在渲染時會自動在相應位置渲染成隱藏的input標籤:<input type="hidden" name="csrfmiddlewaretoken" value="8J4z1wiUEXt0gJSN59dLMnktrXFW0hv7m4d40Mtl37D7vJZfrxLir9L3jSTDjtG8">每次都是隨機的 表現狀況 在以前咱們提交數據必須`注了配置項MIDDLEWARE裏面的django.middleware.csrf.CsrfViewMiddleware',不然403`爲何要有這個 安全認證機制csrftoken
兩種狀況 當form表單提交數據時 當ajax提交數據時 代碼詳解以下
當form表單提交數據時
form表單裏面要有這個就行 <form action="" method="post"> {% csrf_token %} 用戶名: <input type="text" name="username"> 密碼: <input type="password" name="password"> <input type="submit"> </form>
當ajax提交數據時
{% csrf_token %}會生成隱藏的input標籤 name是csrfmiddlewaretoken固定的values值是隨機的 爲何要這個input標籤 官方源碼解釋 官方文檔中說到,檢驗token時,只比較secret是否和 cookie中的secret值同樣,而不是比較整個token。 token字符串的前32位是 salt(鹽), 後面是加密後的 token(令牌), 經過salt能解密出惟一的secret。 django會驗證表單中的token和cookie中token是否能解出一樣的secret,secret同樣則本次請求合法。 一樣也不難解釋,爲何ajax請求時,須要從cookie中拿取token添加到請求頭中。 第一種方式 {% csrf_token %}---必加 用戶名: <input type="text" id="username"> 密碼: <input type="password" id="password"> <button id="sub">提交</button> <span class="error"></span> <script src="{% static 'js/jquery.js' %}"></script> <script src="{% static 'js/jquery.cookie.js' %}"></script> $('#sub').click(function () { var uname = $('#username').val(); var pwd = $('#password').val(); var csrf = $('[name=csrfmiddlewaretoken]').val(); ---固定寫法得到隨機值 $.ajax({ url:'{% url "login" %}', type:'post', data:{username:uname,password:pwd,csrfmiddlewaretoken:csrf},--發送給後端 success:function (res) {---ret是後端給的 if (res === '1'){ location.href = '/home/'; // http://127.0.0.1:8000/home/ }else{ $('.error').text('用戶名密碼錯誤!'); } } }) }) 第2種方式 {% csrf_token %}---必加 用戶名: <input type="text" id="username"> 密碼: <input type="password" id="password"> <button id="sub">提交</button> <span class="error"></span> <script src="{% static 'js/jquery.js' %}"></script> <script src="{% static 'js/jquery.cookie.js' %}"></script> $('#sub').click(function () { var uname = $('#username').val(); var pwd = $('#password').val(); var csrf = '{{ csrf_token }}'; ---第2種方式固定寫法 csrf_token會得到csrf_token中鍵隨機值 $.ajax({ url:'{% url "login" %}', type:'post', data:{username:uname,password:pwd,csrfmiddlewaretoken:csrf},--發送給後端 success:function (res) {---ret是後端給的 if (res === '1'){ location.href = '/home/'; // http://127.0.0.1:8000/home/ }else{ $('.error').text('用戶名密碼錯誤!'); } } }) }) 第3種 注意:須要引入一個jquery.cookie.js插件。 <script src="{% static 'js/jquery.cookie.js' %}"></script> {% csrf_token %}---必加 用戶名: <input type="text" id="username"> 密碼: <input type="password" id="password"> <button id="sub">提交</button> <span class="error"></span> <script src="{% static 'js/jquery.js' %}"></script> <script src="{% static 'js/jquery.cookie.js' %}"></script> $('#sub').click(function () { var uname = $('#username').val(); var pwd = $('#password').val(); var csrf = '{{ csrf_token }}'; ---第2種方式固定寫法 csrf_token會得到csrf_token中鍵隨機值 $.ajax({ url:'{% url "login" %}', type:'post', data:{username:uname,password:pwd}, headers:{"X-CSRFToken":$.cookie('csrftoken')}--固定寫法值是cookie success:function (res) {---ret是後端給的 if (res === '1'){ location.href = '/home/'; // http://127.0.0.1:8000/home/ }else{ $('.error').text('用戶名密碼錯誤!'); } } }) })
form表單上傳文件 ajax上傳文件
理論 form表單提交的文件在request.FILES裏面 若是不改消息格式則request.FILES裏面爲空 修改消息格式 在form表單中加入 enctype="multipart/form-data" 得到文件對象(句柄)file_obj = request.FILES.get('file') 括號裏面的file就是 後端<input type="file" name="file">標籤對應的name值 得到文件名稱 就用文件對象.name 及就是 file_obj.name 有了文件對象(句柄) 和原文件名字就能夠寫入文件了 步驟 第1步 修改消息格式 在form表單中加入 enctype="multipart/form-data" 第2步 後端代碼得到文件對象 與名字就能夠寫人文件了 實現代碼以下
前端代碼
前端代碼 <form action="" method="post" enctype="multipart/form-data">--到定義 {% csrf_token %} 用戶名: <input type="text" name="username"> 密碼: <input type="password" name="password"> 上傳文件: <input type="file" name="file"> <input type="submit"> </form> 後端代碼 def upload(request): if request.method == 'GET': print(settings.BASE_DIR) #/static/ return render(request,'upload.html') else: #print(request.POST)--獲取的是對象 裏面有文件名 #print(request.FILES) --對象 文件對象 存在內存中 若是不改消息格式裏面沒東西 uname = request.POST.get('username') pwd = request.POST.get('password') file_obj = request.FILES.get('file')---獲取文件句柄對象 print(file_obj.name) #開班典禮.pptx with open(file_obj.name,'wb') as f: # for i in file_obj: --怕文件中沒有換行 會爆內存 # f.write(i) for chunk in file_obj.chunks():---通常用這種一次讀取65536個字節 f.write(chunk) return HttpResponse('ok') 擴展內容 怎麼修改chunks()默認讀取子節? 配置文件修改chunks() from django.conf import settings與from 項目名 import settings的區別? from django.conf import settings是內置的另外一個配置文件,外層settings沒有的內層裏面可能有 from 項目名 import settings是當前項目外層的配置文件 外層有的就覆蓋了內層的 用法上from django.conf import settings更厲害 外層配配置文件沒有的可能能在內層配置找到
第1步綁定點擊事件 第2步 點擊 觸發事件 執行匿名函數 函數裏面邏輯利用js得到想要的結果 var file = $('[type=file]')[0].files[0];--獲取上傳對象 第3步 建立FormData對象 藉助他上傳 第4步 將匿名函數或的的想要的結果append 鍵值對的形式加進去 第5步 ajax上傳加入固定寫法 叫django不要處理代碼示例 processData:false,--固定寫法 叫django不要處理 contentType:false,--固定寫法 叫django不要處理 後端代碼不變
多加一個參數multiple
後端也要改
{% csrf_token %} 用戶名: <input type="text" name="username"> 密碼: <input type="password" name="password"> 上傳文件: <input type="file" name="file" > <input type="submit"> </form> $('#sub').click(function () { var formdata = new FormData();---建立FormData對象藉助他上傳 var uname = $('#username').val(); var pwd = $('#password').val(); var file = $('[type=file]')[0].files[0];--獲取對象 formdata.append('username',uname); 封裝到對象裏面 formdata.append('password',pwd); formdata.append('file',file); $.ajax({ url:'{% url "upload" %}', type:'post', data:formdata,---發這個 processData:false,--固定寫法 叫django不要處理 contentType:false,--固定寫法 叫django不要處理 success:function (res) {---ret是後端給的 if (res === '1'){ location.href = '/home/'; // 重定向http://127.0.0.1:8000/home/ }else{ $('.error').text('用戶名密碼錯誤!'); } } }) }) 後端 def upload(request): if request.method == 'GET': print(settings.BASE_DIR) #/static/ return render(request,'upload.html') else: #print(request.POST)--獲取的是對象 裏面有文件名 #print(request.FILES) --對象 文件對象 存在內存中 若是不改消息格式裏面沒東西 uname = request.POST.get('username') pwd = request.POST.get('password') file_obj = request.FILES.get('file')---獲取文件句柄對象 print(file_obj.name) #開班典禮.pptx with open(file_obj.name,'wb') as f: # for i in file_obj: --怕文件中沒有換行 會爆內存 # f.write(i) for chunk in file_obj.chunks():---通常用這種一次讀取65536個字節 f.write(chunk) return HttpResponse('ok')
通常咱們後端返回給前端的數據都是字典形式 全部要用到JSON 轉化爲特殊格式,便於解析回去 3種方式 第一種方式利用 json模塊 low逼寫法 後端要反序列化 import json et_data_json = json.dumps(要轉化的字典dic,ensure_ascii=False) var res = JSON.parse(res); -- 反序列化變成js自定義對象 第2種方式 高大尚寫法 import json ret_data_json = json.dumps(要轉化的字典dic,ensure_ascii=False) return HttpResponse(ret_data_json,content_type='application/json') 會自動轉化爲json數據 前端就不要反序列化了 第3種寫法 最終版 from django.http import JsonResponse return JsonResponse(字典)
--------------第一種 html頁面 {% csrf_token %}---必加 用戶名: <input type="text" id="username"> 密碼: <input type="password" id="password"> <button id="sub">提交</button> <span class="error"></span> <script src="{% static 'js/jquery.js' %}"></script> <script src="{% static 'js/jquery.cookie.js' %}"></script> $('#sub').click(function () { var uname = $('#username').val(); var pwd = $('#password').val(); var csrf = $('[name=csrfmiddlewaretoken]').val(); ---固定寫法得到隨機值 $.ajax({ url:'{% url "login" %}', type:'post', data:{username:uname,password:pwd,csrfmiddlewaretoken:csrf},--發送給後端 success:function (res) { var res = JSON.parse(res); -- 反序列化變成js自定義對象 if (res.status === 1000){ // $('.error').text('登陸成功'); location.href = '/home/'; // http://127.0.0.1:8000/home/ }else{ $('.error').text(res.msg); } } }) }) 後端代碼 def jsontest(request): if request.method == 'GET': return render(request,'jsontest.html') else: username = request.POST.get('username') pwd = request.POST.get('password') ret_data = {'status':None,'msg':None} if username == 'chao' and pwd == '123': ret_data['status'] = 1000 # 假設1000狀態碼登陸成功本身設置的 ret_data['msg'] = '登陸成功' else: ret_data['status'] = 1001 # 假設1001狀態碼登陸失敗本身設置的 ret_data['msg'] = '登陸失敗' et_data_json = json.dumps(ret_data,ensure_ascii=False) return HttpResponse(et_data_json) --------------第2種方式 後端代碼 def jsontest(request): if request.method == 'GET': return render(request,'jsontest.html') else: username = request.POST.get('username') pwd = request.POST.get('password') ret_data = {'status':None,'msg':None} if username == 'chao' and pwd == '123': ret_data['status'] = 1000 # 假設1000狀態碼登陸成功本身設置的 ret_data['msg'] = '登陸成功' else: ret_data['status'] = 1001 # 假設1001狀態碼登陸失敗本身設置的 ret_data['msg'] = '登陸失敗' return HttpResponse(ret_data_json,content_type='application/json') 會自動轉化爲json數據 前端就不要反序列化了 html頁面 {% csrf_token %}---必加 用戶名: <input type="text" id="username"> 密碼: <input type="password" id="password"> <button id="sub">提交</button> <span class="error"></span> <script src="{% static 'js/jquery.js' %}"></script> <script src="{% static 'js/jquery.cookie.js' %}"></script> $('#sub').click(function () { var uname = $('#username').val(); var pwd = $('#password').val(); var csrf = $('[name=csrfmiddlewaretoken]').val(); ---固定寫法得到隨機值 $.ajax({ url:'{% url "login" %}', type:'post', data:{username:uname,password:pwd,csrfmiddlewaretoken:csrf},--發送給後端 success:function (res) { //不要這個了 var res = JSON.parse(res); -- 反序列化變成js自定義對象 if (res.status === 1000){ // $('.error').text('登陸成功'); location.href = '/home/'; // http://127.0.0.1:8000/home/ }else{ $('.error').text(res.msg); } } }) }) 第3種方式 from django.http import JsonResponse 後端代碼 def jsontest(request): if request.method == 'GET': return render(request,'jsontest.html') else: username = request.POST.get('username') pwd = request.POST.get('password') ret_data = {'status':None,'msg':None} if username == 'chao' and pwd == '123': ret_data['status'] = 1000 # 假設1000狀態碼登陸成功本身設置的 ret_data['msg'] = '登陸成功' else: ret_data['status'] = 1001 # 假設1001狀態碼登陸失敗本身設置的 ret_data['msg'] = '登陸失敗' return JsonResponse(ret_data) 會自動轉化爲json數據 前端就不要反序列化了 html頁面 {% csrf_token %}---必加 用戶名: <input type="text" id="username"> 密碼: <input type="password" id="password"> <button id="sub">提交</button> <span class="error"></span> <script src="{% static 'js/jquery.js' %}"></script> <script src="{% static 'js/jquery.cookie.js' %}"></script> $('#sub').click(function () { var uname = $('#username').val(); var pwd = $('#password').val(); var csrf = $('[name=csrfmiddlewaretoken]').val(); ---固定寫法得到隨機值 $.ajax({ url:'{% url "login" %}', type:'post', data:{username:uname,password:pwd,csrfmiddlewaretoken:csrf},--發送給後端 success:function (res) { //不要這個了 var res = JSON.parse(res); -- 反序列化變成js自定義對象 if (res.status === 1000){ // $('.error').text('登陸成功'); location.href = '/home/'; // http://127.0.0.1:8000/home/ }else{ $('.error').text(res.msg); } } }) })
1 生成html標籤 2 保留原來的數據 3 校驗用戶提交的數據 如何給生成的標籤加樣式
第1步 在views.py文件中 導入from django import forms模塊 定義一個類 繼承與forms.Form 名字隨意 繼承forms.Form 第2步 修改forms.後面的 變動不一樣屬性 第3步 修改forms.widgets.後面的 變動不一樣標籤 第4步 實列化這個類 傳給後端 第5步 寫後端代碼 {{對象.字段.label }}就是自定義名字 {{ 對象.字段 }} 就會生成標籤 {{ 對象.字段.errors.0 }}就會生成錯誤信息 第1個 from django import forms #生成用戶名輸入框 name對應username vluse對應用戶輸入的值 class UserInfo(forms.Form): username=forms.CharField( label='用戶名:', initial="張三",#默認值 widget=forms.widgets.TextInput, ) #生成密碼輸入框 name對應password vluse對應用戶輸入的值 password=forms.CharField( label='密碼:', widget=forms.widgets.PasswordInput(attrs={'class':'c1'}),---attrs裏面能夠添加屬性 ) #生成單選框 默認下拉框 name對應 sex vluse對應用戶選擇的值 sex = forms.ChoiceField( choices=((1,'女'),(2,'男'),),#元祖套列表或元祖套元祖 # widget=forms.RadioSelect,----修改爲這樣變成小圓點選擇框 # widget=forms.widgets.Select,---這是下拉框 默認就是 ) #生成多選框 默認下拉框 name對應 hobby vluse對應用戶選擇的值 hobby = forms.MultipleChoiceField( choices= ((1,'喝酒'),(2,'抽菸'),(3,'燙頭')), # widget=forms.SelectMultiple,---這是下拉框 默認就是 widget=forms.CheckboxSelectMultiple,---修改爲小方塊選擇框 ) #生成 選中框 name對應 remember_me remember_me = forms.ChoiceField( label='記住我', widget=forms.CheckboxInput, ) #生成 日期選擇框 name對應 bday bday = forms.DateField( label='出生日期', # 日期類型必須加上日期屬性 widget=forms.DateInput(attrs={'type':'date'}), ) def index(request): if request.method == 'GET': u_obj = UserInfo()#實列化對象 return render(request,'index.html',{'u_obj':u_obj}) else: u_obj = UserInfo(request.POST) #用戶提交的數據給類 進行實例化 if u_obj.is_valid():#效驗用戶數據 # {'username': 'a范德薩水電費', 'password': '1111'} print('正確數據',u_obj.cleaned_data) #校驗成功以後的數據cleaned_data return HttpResponse('ok') else: # print('錯誤信息',u_obj.errors) return render(request,'index.html',{'u_obj':u_obj}) 前端模板寫法 <!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>Title</title> <style> .c1{ background-color: red; } </style> </head> <body> <h1>某某登陸頁面</h1> {#{{ u_obj.errors }}#}所有報錯信息 <form action="" method="post" novalidate> {% csrf_token %} 安全驗證 {# 用戶名: <input type="text" name="username">#} {# 密碼: <input type="password" name="password">#} {{ u_obj.username.label }} {{ u_obj.username }} {{ u_obj.username.errors.0 }} </div> <div> {{ u_obj.password.label }} {{ u_obj.password }} {{ u_obj.password.errors.0 }} </div> <div> {{ u_obj.r_password.label }} {{ u_obj.r_password }} {{ u_obj.r_password.errors.0 }} </div> <input type="submit"> </form>
默認自動保留 password不會自動保留數據在widget裏面添加render_value=True就能夠強制留下 r_password = forms.CharField( label='確認密碼:', widget=forms.widgets.PasswordInput(attrs={'class': 'c1'}, render_value=True), ) render_value=True強制留
u_obj.password.errors.0 得到第一個錯誤數據 常見屬性 min_length設置用戶輸入長度最小值 max_length設置用戶輸入長度最大值 required=True, #不容許輸入爲空,值爲False就能夠爲空 自定義錯誤信息後就不會顯示英文的了 error_messages={ 'required':'不能爲空', 'min_length':'過短了!', 'max_length':'太長了!', }, 注意瀏覽器會自動幫你效驗 要想瀏覽器不效驗 在前端代碼設置(novalidate)提示瀏覽器不要多管閒事 <form action="" method="post" novalidate>
下面的代碼實列
username=forms.CharField( label='用戶名:', # initial='張三' #默認值 # min_length=6, #最小值爲6位 # required=True, #不容許爲空,值爲False就能夠爲空 # widget=forms.widgets.TextInput, # max_length=8, error_messages={ 'required':'不能爲空', 'min_length':'過短了!', 'max_length':'太長了!', }, validators=[RegexValidator(r'^a','必須以a開頭!'),RegexValidator(r'b$','必須以b結尾!')] # validators=[mobile_validate,] #a范德薩水電費 )
第一步引入模塊from django.core.validators import RegexValidator 第2步定義規則 能夠定義多個規則 validators=[RegexValidator(r'^a','必須以a開頭!'),RegexValidator(r'b$','必須以b結尾!')] 第一個參數是正則 第2個參數是錯誤信息
下面是代碼實列
username=forms.CharField( label='用戶名:', initial='張三' #默認值 min_length=6, #最小值爲6位 required=True, #不容許爲空,值爲False就能夠爲空 widget=forms.widgets.TextInput, max_length=8, error_messages={ 'required':'不能爲空', 'min_length':'過短了!', 'max_length':'太長了!', }, validators=[RegexValidator(r'^a','必須以a開頭!'),RegexValidator(r'b$','必須以b結尾!')]
當正則效驗 與基礎效驗 知足不了 咱們就須要 自定義驗證規則了( ) 第1步引入模塊 from django.core.exceptions import ValidationError import re 第2步定義一個函數 函數裏面value是形參 傳要驗證的字符串 mobile_re是利用re模塊編譯出來的正則規則 利用ValidationError拋出錯誤 def mobile_validate(value): mobile_re = re.compile(r'^(13[0-9]|15[012356789]|17[678]|18[0-9]|14[57])[0-9]{8}$') if not mobile_re.match(value): raise ValidationError('手機號碼格式錯誤') 第3步 在類裏面 驗證類裏面加入· validators=[定義的函數名,]
代碼實列
from django.core.validators import RegexValidator from django.core.exceptions import ValidationError import re def mobile_validate(value): mobile_re = re.compile(r'^(13[0-9]|15[012356789]|17[678]|18[0-9]|14[57])[0-9]{8}$') if not mobile_re.match(value): raise ValidationError('手機號碼格式錯誤') class UserInfo(forms.Form): username=forms.CharField( label='用戶名:', # initial='張三' #默認值 # min_length=6, #最小值爲6位 # required=True, #不容許爲空,值爲False就能夠爲空 # widget=forms.widgets.TextInput, # max_length=8, error_messages={ 'required':'不能爲空', 'min_length':'過短了!', 'max_length':'太長了!', }, validators=[RegexValidator(r'^a','必須以a開頭!'),RegexValidator(r'b$','必須以b結尾!')] validators=[mobile_validate,] #a范德薩水電費 ) password=forms.CharField( label='密碼:', widget=forms.widgets.PasswordInput(attrs={'class':'c1'},render_value=True), ) r_password = forms.CharField( label='確認密碼:', widget=forms.widgets.PasswordInput(attrs={'class': 'c1'}, render_value=True), ) # 局部鉤子 def clean_username(self): value = self.cleaned_data.get('username') if '666' in value: raise ValidationError('光喊666是不行的!') else: return value # 全局鉤子 def clean(self): password = self.cleaned_data.get('password') r_password = self.cleaned_data.get('r_password') if password == r_password: return self.cleaned_data else: # raise ValidationError('兩次密碼不一致!!!!') self.add_error('r_password','兩次密碼不一致~~~~') # 給單獨的某個字段加錯誤信息 def index(request): if request.method == 'GET': u_obj = UserInfo() return render(request,'index.html',{'u_obj':u_obj}) else: 效驗 u_obj = UserInfo(request.POST) #{'username':'','password':'123'} print(u_obj.fields) # u_obj.is_valid() #校驗用戶提交的數據,所有校驗成功返回True,任意一個失敗都返回False if u_obj.is_valid(): # {'username': 'a范德薩水電費', 'password': '1111'} print('正確數據',u_obj.cleaned_data) #校驗成功以後的數據cleaned_data return HttpResponse('ok') else: # print('錯誤信息',u_obj.errors) return render(request,'index.html',{'u_obj':u_obj})
第1步 咱們在Fom類中定義 clean_字段() 方法,就可以實現對特定字段進行校驗。 注意事項 效驗順序是先效驗字段裏面的效驗規則 而後在效驗局部鉤子 最後下一字段 實列寫法(cleaned_data是效驗之後獲得的數據) def clean_username(self): value = self.cleaned_data.get('username') if '666' in value: raise ValidationError('光喊666是不行的!')--錯誤信息 else: return value--必定要返回否則會吧username對應的value剔除 鉤子是寫在類裏面
代碼實列
from django.core.validators import RegexValidator from django.core.exceptions import ValidationError import re def mobile_validate(value): mobile_re = re.compile(r'^(13[0-9]|15[012356789]|17[678]|18[0-9]|14[57])[0-9]{8}$') if not mobile_re.match(value): raise ValidationError('手機號碼格式錯誤') class UserInfo(forms.Form): username=forms.CharField( label='用戶名:', # initial='張三' #默認值 # min_length=6, #最小值爲6位 # required=True, #不容許爲空,值爲False就能夠爲空 # widget=forms.widgets.TextInput, # max_length=8, error_messages={ 'required':'不能爲空', 'min_length':'過短了!', 'max_length':'太長了!', }, validators=[RegexValidator(r'^a','必須以a開頭!'),RegexValidator(r'b$','必須以b結尾!')] validators=[mobile_validate,] #a范德薩水電費 ) password=forms.CharField( label='密碼:', widget=forms.widgets.PasswordInput(attrs={'class':'c1'},render_value=True), ) r_password = forms.CharField( label='確認密碼:', widget=forms.widgets.PasswordInput(attrs={'class': 'c1'}, render_value=True), ) # 局部鉤子 def clean_username(self): value = self.cleaned_data.get('username') if '666' in value: raise ValidationError('光喊666是不行的!') else: return value # 全局鉤子 def clean(self): password = self.cleaned_data.get('password') r_password = self.cleaned_data.get('r_password') if password == r_password: return self.cleaned_data else: # raise ValidationError('兩次密碼不一致!!!!') self.add_error('r_password','兩次密碼不一致~~~~') # 給單獨的某個字段加錯誤信息 def index(request): if request.method == 'GET': u_obj = UserInfo() return render(request,'index.html',{'u_obj':u_obj}) else: 效驗 u_obj = UserInfo(request.POST) #{'username':'','password':'123'} print(u_obj.fields) # u_obj.is_valid() #校驗用戶提交的數據,所有校驗成功返回True,任意一個失敗都返回False if u_obj.is_valid(): # {'username': 'a范德薩水電費', 'password': '1111'} print('正確數據',u_obj.cleaned_data) #校驗成功以後的數據cleaned_data return HttpResponse('ok') else: # print('錯誤信息',u_obj.errors) return render(request,'index.html',{'u_obj':u_obj})
句部鉤子所有指行完 在執行全局 好比多個字段對比效驗, 好比確認密碼 函數名固定寫法 def clean(self): password = self.cleaned_data.get('password') r_password = self.cleaned_data.get('r_password') if password == r_password:#效驗成功了L return self.cleaned_data---固定寫法 cleaned_data源碼裏有 else: # raise ValidationError('兩次密碼不一致!!!!')不用由於給全局了 self.add_error('r_password','兩次密碼不一致~~~~') # 給單獨的某個字段加錯誤信息
代碼實列
from django.core.validators import RegexValidator from django.core.exceptions import ValidationError import re def mobile_validate(value): mobile_re = re.compile(r'^(13[0-9]|15[012356789]|17[678]|18[0-9]|14[57])[0-9]{8}$') if not mobile_re.match(value): raise ValidationError('手機號碼格式錯誤') class UserInfo(forms.Form): username=forms.CharField( label='用戶名:', # initial='張三' #默認值 # min_length=6, #最小值爲6位 # required=True, #不容許爲空,值爲False就能夠爲空 # widget=forms.widgets.TextInput, # max_length=8, error_messages={ 'required':'不能爲空', 'min_length':'過短了!', 'max_length':'太長了!', }, validators=[RegexValidator(r'^a','必須以a開頭!'),RegexValidator(r'b$','必須以b結尾!')] validators=[mobile_validate,] #a范德薩水電費 ) password=forms.CharField( label='密碼:', widget=forms.widgets.PasswordInput(attrs={'class':'c1'},render_value=True), ) r_password = forms.CharField( label='確認密碼:', widget=forms.widgets.PasswordInput(attrs={'class': 'c1'}, render_value=True), ) # 局部鉤子 def clean_username(self): value = self.cleaned_data.get('username') if '666' in value: raise ValidationError('光喊666是不行的!') else: return value # 全局鉤子 def clean(self): password = self.cleaned_data.get('password') r_password = self.cleaned_data.get('r_password') if password == r_password: return self.cleaned_data else: # raise ValidationError('兩次密碼不一致!!!!') self.add_error('r_password','兩次密碼不一致~~~~') # 給單獨的某個字段加錯誤信息 def index(request): if request.method == 'GET': u_obj = UserInfo() return render(request,'index.html',{'u_obj':u_obj}) else: 效驗 u_obj = UserInfo(request.POST) #{'username':'','password':'123'} print(u_obj.fields) # u_obj.is_valid() #校驗用戶提交的數據,所有校驗成功返回True,任意一個失敗都返回False if u_obj.is_valid(): # {'username': 'a范德薩水電費', 'password': '1111'} print('正確數據',u_obj.cleaned_data) #校驗成功以後的數據cleaned_data return HttpResponse('ok') else: # print('錯誤信息',u_obj.errors) return render(request,'index.html',{'u_obj':u_obj})
# 批量添加屬性樣式 def __init__(self,*args,**kwargs): super().__init__(*args,**kwargs) for field_name,field in self.fields.items(): #orderdict(('username',charfield對象)) field.widget.attrs.update({'class':'form-control'})
class BookModelForm(forms.ModelForm): # 優先級高 # title = forms.CharField( # label='書名2', # ) class Meta: model = models.Book #fields='__all__' fields=['title','publishs'] labels={ 'title':'書名', 'price':'價格', 'publishDate':'出版日期', 'publishs':'出版社', 'authors':'做者', } widgets={ 'publishDate':forms.TextInput(attrs={'type':'date'}), # 'publishDate2':forms.TextInput(attrs={'type':'date'}), } error_messages={ 'title':{'required':'書名不能爲空!',}, 'price':{'required':'不能爲空!',}, 'publishDate':{'required':'不能爲空!',}, 'publishs':{'required':'不能爲空!',}, 'authors':{'required':'不能爲空!',}, } # # def clean_title(self): # pass # def clean(self): # pass def __init__(self,*args,**kwargs): super().__init__(*args,**kwargs) for field_name,field in self.fields.items(): field.widget.attrs.update({'class':'form-control'})
舉個例子,你也許會有個Book 模型,而且你還想建立一個form表單用來添加和編輯書籍信息到這個模型中。 在這種狀況下,在form表單中定義字段將是冗餘的,由於咱們已經在模型中定義了那些字段。 基於這個緣由,Django 提供一個輔助類來讓咱們能夠從Django 的模型建立Form,這就是ModelForm。 form與model的終極結合,會根據你model中的字段轉換成對應的form字段,而且並你生成標籤等操做。
第一步定義一個類 名字隨便取 最好有含義 列入BookModelForm 類裏面定義 class Meta: model = models.Book #fields='__all__' 拿到全部字段 生成from字段 class BookModelForm(forms.ModelForm):#類目隨便取 # 優先級高 # title = forms.CharField( # label='書名2', # ) class Meta: model = models.Book#找到book表 fields='__all__' #拿到全部字段 生成from字段 #fields=['title','publishs'] labels={ 'title':'書名', 'price':'價格', 'publishDate':'出版日期', 'publishs':'出版社', 'authors':'做者', } widgets={ 'publishDate':forms.TextInput(attrs={'type':'date'}), # 'publishDate2':forms.TextInput(attrs={'type':'date'}), } error_messages={ 'title':{'required':'書名不能爲空!',}, 'price':{'required':'不能爲空!',}, 'publishDate':{'required':'不能爲空!',}, 'publishs':{'required':'不能爲空!',}, 'authors':{'required':'不能爲空!',}, } # # def clean_title(self): 鉤子 # pass # def clean(self): # pass def __init__(self,*args,**kwargs):#仍是和from同樣給全部字段添加樣式 super().__init__(*args,**kwargs) for field_name,field in self.fields.items(): field.widget.attrs.update({'class':'form-control'})
python manage.py createsuperuser 輸入用戶名:wuchao 郵箱不用輸 直接回車 輸入密碼:必須超過8位,而且別太簡單
admin註冊
from django.contrib import admin # Register your models here. from app01 import models admin.site.register(models.Author) admin.site.register(models.AuthorDetail) admin.site.register(models.Publish) admin.site.register(models.Book)
admin添加用戶
python manage.py createsuperuser 輸入用戶名:wuchao 郵箱不用輸 直接回車 輸入密碼:必須超過8位,而且別太簡單
admin註冊
from django.contrib import admin # Register your models here. from app01 import models admin.site.register(models.Author) admin.site.register(models.AuthorDetail) admin.site.register(models.Publish) admin.site.register(models.Book)
什麼是cookie及 應用場景 cookie的運用方法?
什麼是cookie?
定義:cookie是服務器讓瀏覽器保存在瀏覽器本地的鍵值對 緣由:http是無狀態,每次請求之間沒有任何關係,沒法保存狀態。使用cookie來保存一些狀態。 實列 用戶登陸 登陸成功向其客戶端發送一個令牌 (保存在用戶器上的鍵值對) 用於下次確認身份
1.經過js設置cookie js查看cookie document. cookie js設置cookie 注意路徑問題path 默認爲空 有則覆蓋 無則增長 document. cookie = ' k1=wy222 ;path=/ ' 注意: path不一樣會致使設置不一樣. path的做用 /,當前網站中全部的URL都能讀取到此值. ",只能在當前頁面訪問的到此數據 /index/ ,只能在/index/xxx的網頁中查看. 經過jquery設置 有則覆蓋 無則增長 $. cookie('k1', 'wy222' ,{path:'/'}) 經過py文件設置 # 設置cookie data.set_cookie('a1','1',path='/') data.set_cookie('a2','2',path='') data.set_cookie('a3','3',path='/test/') # 讀取cookie request.COOKIES.get('cookie鍵') #判斷有沒這個值 在下面3種狀況均可以設置cookie return HttpResponse('...') return render('...') return redirect('...')
# 用戶登陸成功 result = redirect('/index/') result.set_cookie('xxxxxxxx',user) return result 用戶輸入index網址 後臺進行判斷 def index(request): """ 博客後臺首頁 :param request: :return: """ user = request.COOKIES.get('xxxxxxxx')#判斷有沒這個值 if not user: return redirect('/login/') return render(request,'index.html',{'user':user}) 在下面3種狀況均可以設置cookie return HttpResponse('...') return render('...') return redirect('...') 必須背會一下三個參數: key 鍵, value='' 值, max_age=None 秒 多少秒後失效 path 路徑 菜鳥教程 https://www.runoob.com/js/js-cookies.html
![1570527138385](file:///C:/Users/86131/AppData/Roaming/Typora/typora-user-images/1570527138385.png)
依賴cookie 是一種存儲數據的方式,依賴於cookie, 實現本質: 用戶向服務端發送請求,服務端作兩件事:第一步爲此用戶開闢一個獨立的空間來存放當前用戶獨有的值.第2步生成隨機字符串發給客戶端 他保存在遊覽器中 在空間中如何想要設置值: request.session['x1'] = 123 request.session['x2'] = 456 在空間中取值: request.session['x2'] request.session.get('x2') 推薦 視圖函數中的業務操做處理完畢,給用戶響應,在響應時會 將隨機字符串存儲到用戶瀏覽器的cookie中. 數據 django默認存在數據庫中 裝飾器
![1570528618057](file:///C:/Users/86131/AppData/Roaming/Typora/typora-user-images/1570528618057.png)
![1570528714941](file:///C:/Users/86131/AppData/Roaming/Typora/typora-user-images/1570528714941.png)
cookie和session的區別?
答: cookie是存儲在客戶端瀏覽器上的鍵值對,發送請求時瀏 覽器會自動攜帶. session是一種存儲數據方式,基於cookie 實現,將數據存儲在服務端(django默認存儲到數據庫). 其本質是:用戶向服務端發送請求,服務端作兩件事:生成隨機字符串; 爲此用戶開闢一個獨立的空間來存放當前用戶獨有的值. 在空間中如何想要設置值: request.session['x1'] = 123 request.session['x2'] = 456 在空間中取值: request.session['x2'] request.session.get('x2') 視圖函數中的業務操做處理完畢,給用戶響應,在響應時會 將隨機字符串存儲到用戶瀏覽器的cookie中.
SESSION_COOKIE_NAME = "sessionid" # Session的cookie保存在瀏覽器上時的key,即:sessionid=隨機字符串 SESSION_COOKIE_DOMAIN = None #那個域名能夠用 讀取的到 none表明所有子域名 SESSION_COOKIE_PATH = "/" # Session的cookie保存的路徑 /默認全部的 SESSION_COOKIE_HTTPONLY = True # 是否Session的cookie只支持http傳輸 True只能夠讀不能夠改 SESSION_COOKIE_AGE = 1209600 #單位秒 Session的cookie失效日期(2周) SESSION_EXPIRE_AT_BROWSER_CLOSE = False # 是否關閉瀏覽器使得Session過時 SESSION_SAVE_EVERY_REQUEST = False # 是否每次請求都保存Session,默認false定時過時時間 若是改成true刷新一次過時時間程序計算
session如何設置過時時間?
SESSION_COOKIE_AGE = 1209600 # Session的 cookie失效日期(2周)
session默認存儲能夠放在其餘地方嗎?
小系統:默認放在數據庫便可. 大系統:緩存(redis) 在settings文件 裏面加入裏面的代碼 # 文件 # SESSION_ENGINE = 'django.contrib.sessions.backends.file' # SESSION_FILE_PATH = '/sssss/' # 緩存(內存) # SESSION_ENGINE = 'django.contrib.sessions.backends.cache' # SESSION_CACHE_ALIAS = 'default' # # CACHES = { # 'default': { # 'BACKEND': 'django.core.cache.backends.locmem.LocMemCache', # 'LOCATION': 'unique-snowflake', # } # } # 緩存(redis) # SESSION_ENGINE = 'django.contrib.sessions.backends.cache' # SESSION_CACHE_ALIAS = 'default' # CACHES = { # "default": { # "BACKEND": "django_redis.cache.RedisCache", # "LOCATION": "redis://127.0.0.1:6379", # "OPTIONS": { # "CLIENT_CLASS": "django_redis.client.DefaultClient", # "CONNECTION_POOL_KWARGS": {"max_connections": 100} # # "PASSWORD": "密碼", # } # } # }
操做session
# 設置(添加&修改) request.session['x1'] = 123 request.session['x2'] = 456 # 讀取 request.session['xx'] request.session.get('xx') # 刪除 del request.session['xx'] 實際上是修改了過時時間 內容總結 1. 裝飾器要加入functools.wrap裝飾 2. orm字段中的verbose_name 3. 路由系統中記得加入終止符 $ 4. 用戶名和密碼檢測 5. 模板查找順序 request.session.keys() request.session.values() request.session.items() request.session.set_expiry(value) request.session.session_key
document.cookie = 'k1=wy222;path=/' $.cookie('k1','wy222',{path:'/'}) 注意:path不一樣會致使設置不一樣.
/ , 當前網站中全部的URL都能讀取到此值. "",只能在當前頁面訪問的到此數據. /index/ ,只能在/index/xxx 的網頁中查看.
爲何要有functools 由於若是多個函數被兩個裝飾器裝飾時就報錯,由於兩個函數名同樣,第二個函數再去裝飾的話就報錯. 而增長@functools.wraps(f), 能夠保持當前裝飾器去裝飾的函數的 name 的值不變 因此須要他 理論不懂 看代碼實列
當沒有 functools時
def wrapper(f): def inner(*args,**kwargs): '''我是內層函數inner''' ret = f(*args,**kwargs) return ret return inner #@wrapper等效與index=wrapper(index) @wrapper def index(a1,a2): """我是原函數index""" return a1+a2 index(1,2) print(index.__name__) #查看此處index函數名 打印結果是--inner print(index.__doc__)#查看此處index函數的註釋打 結果是 ---我是內層函數inner
當有functools時
import functools def wrapper(f): @functools.wraps(f) def inner(*args,**kwargs): '''我是內層函數inner''' ret = f(*args,**kwargs) return ret return inner #@wrapper等效與index=wrapper(index) @wrapper def index(a1,a2): """我是原函數index""" return a1+a2 index(1,2) print(index.__name__) #查看此處index函數名 打印結果是--index print(index.__doc__)#查看此處index函數的註釋打 結果是 ---我是原函數index
對比發現functools能夠還本來質 解決了 多個函數被兩個裝飾器裝飾時就報錯