1.1 test的使用php
test 測試是否符合條件 返回true or falsecss
1.2 exec的使用html
exec 從字符串中截取匹配的字符前端
1.3 分組python
-/g /m /i 分組mysql
JavaScript 正則表達式
- test 測試是否符合條件 返回true or false
- exec 從字符串中截取匹配的字符jquery
test 判斷字符串是否包含數字 判斷字符串是否全是數字 var pattern=/\d+/; pattern.test('aaa123bbb'); true var pattern=/^\d+$/; pattern.test('aaa123bbb'); false exec 截取數字 rep = /\d+/; str = "wangshen_67_houyafa_20"; rep.exec(str); ["67", index: 9, input: "wangshen_67_houyafa_20", groups: undefined] 分組 pattern=/Java(\w*)/g; /Java(\w*)/g str="JavaScript is more fun than Java or JavaBeans!"; "JavaScript is more fun than Java or JavaBeans!" pattern.exec(str); (2) ["JavaScript", "Script", index: 0, input: "JavaScript is more fun than Java or JavaBeans!", groups: undefined] pattern.exec(str); (2) ["Java", "", index: 28, input: "JavaScript is more fun than Java or JavaBeans!", groups: undefined] pattern.exec(str); (2) ["JavaBeans", "Beans", index: 36, input: "JavaScript is more fun than Java or JavaBeans!", groups: undefined] \g 是一個迭代器,每運行一次生成下一個 pattern.exec(str); ["JavaScript", index: 0, input: "JavaScript is more fun than Java or JavaBeans!", groups: undefined] pattern.exec(str); ["Java", index: 28, input: "JavaScript is more fun than Java or JavaBeans!", groups: undefined] pattern.exec(str); ["JavaBeans", index: 36, input: "JavaScript is more fun than Java or JavaBeans!", groups: undefined] pattern.exec(str); null pattern.exec(str); ["JavaScript", index: 0, input: "JavaScript is more fun than Java or JavaBeans!", groups: undefined] pattern.exec(str); ["Java", index: 28, input: "JavaScript is more fun than Java or JavaBeans!", groups: undefined] pattern.exec(str); ["JavaBeans", index: 36, input: "JavaScript is more fun than Java or JavaBeans!", groups: undefined] pattern.exec(str); null pattern.exec(str); ["JavaScript", index: 0, input: "JavaScript is more fun than Java or JavaBeans!", groups: undefined] var pattern = /\d+/g; undefined str='aaa123bbb345'; "aaa123bbb345" pattern.exec(str); ["123", index: 3, input: "aaa123bbb345", groups: undefined] pattern.exec(str); ["345", index: 9, input: "aaa123bbb345", groups: undefined] pattern.exec(str); null pattern.exec(str); ["123", index: 3, input: "aaa123bbb345", groups: undefined] pattern.exec(str); ["345", index: 9, input: "aaa123bbb345", groups: undefined] str="JavaScript is more fun than xxxJavaxxx or JavaBeans!"; "JavaScript is more fun than xxxJavaxxx or JavaBeans!" pattern.exec(str); null pattern.exec(str); (2) ["JavaScript", "Script", index: 0, input: "JavaScript is more fun than xxxJavaxxx or JavaBeans!", groups: undefined] pattern.exec(str); (2) ["Javaxxx", "xxx", index: 31, input: "JavaScript is more fun than xxxJavaxxx or JavaBeans!", groups: undefined] pattern.exec(str); (2) ["JavaBeans", "Beans", index: 42, input: "JavaScript is more fun than xxxJavaxxx or JavaBeans!", groups: undefined] pattern.exec(str); null pattern=/\bJava(\w*)\b/g; /\bJava(\w*)\b/g pattern.exec(str); (2) ["JavaScript", "Script", index: 0, input: "JavaScript is more fun than xxxJavaxxx or JavaBeans!", groups: undefined] pattern.exec(str); (2) ["JavaBeans", "Beans", index: 42, input: "JavaScript is more fun than xxxJavaxxx or JavaBeans!", groups: undefined] pattern.exec(str); null pattern.exec(str); (2) ["JavaScript", "Script", index: 0, input: "JavaScript is more fun than xxxJavaxxx or JavaBeans!", groups: undefined] pattern.exec(str); (2) ["JavaBeans", "Beans", index: 42, input: "JavaScript is more fun than xxxJavaxxx or JavaBeans!", groups: undefined] \b的使用 \i 不區分大小寫 \m 多行的使用 默認是多行匹配 即支持多行尋找 只是針對^$時候,對於多行的處理 str="JavaScript is more fun than \nJava or JavaBeans!" "JavaScript is more fun than Java or JavaBeans!" rep=/^Java\w*/g; /^Java\w*/g rep.exec(str); ["JavaScript", index: 0, input: "JavaScript is more fun than ↵Java or JavaBeans!", groups: undefined] rep.exec(str); null rep=/^Java\w*/mg; /^Java\w*/gm rep.exec(str); ["JavaScript", index: 0, input: "JavaScript is more fun than ↵Java or JavaBeans!", groups: undefined] rep.exec(str); ["Java", index: 29, input: "JavaScript is more fun than ↵Java or JavaBeans!", groups: undefined] rep.exec(str); null
2.1 js與jq的綁定事件的方式的不通(是否有on)nginx
2.2 return 方式來阻塞後續事件的發生(此時不展開,在上一篇文章中有提到)git
2.3 注意submit 與checkbook事件執行的前後順序(綁定click事件)web
submit動做 執行前後
checkbok的事件 執行前後
實例;表單驗證
實際就是別人寫好了模板,樣式,作個告終,在後面的項目部分,或使用這些個前端組件,進行快速的前端開發
幾個比較出名的組件
easyui
jqueryui
bootstrap
組件的補充內容
3.一、響應式 @media 根據web界面的長框等因素使用不一樣的樣式。即自適應
3.二、字體圖標 以bootstrap爲例,bootstrap在使用圖標的時候應該注意到字體文件的導入。(以前博客的font awesome圖標不要導入字體)
3.三、滾動圖 bxslider
import socket server=socket.socket() server.bind(('0.0.0.0',10086)) server.listen(5) while True: conn,add=server.accept() tmp_recv=conn.recv(1024) conn.send(b'HTTP/1.1 200 OK\r\n\r\n') conn.send('hello world,你好世界'.encode('gbk'))#此處若是用utf-8 那麼瀏覽器會顯示什麼 conn.close()
-------------------
print(tmp_recv)
b'
GET / HTTP/1.1\r\n
Host: 127.0.0.1:10086\r\n
Connection: keep-alive\r\n
Pragma: no-cache\r\n
Cache-Control: no-cache\r\n
Upgrade-Insecure-Requests: 1\r\n
User-Agent: Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/69.0.3497.100 Safari/537.36\r\n
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,image/apng,*/*;q=0.8\r\n
Accept-Language: zh-CN,zh;q=0.9\r\n
Cookie: csrftoken=VBVNk321AAGMuygu2OWoRXHUc2LiIspKoPaQfN1AbSY2WEUWPQS09ghoop1LzXFw; sessionid=os5tnm6lqwxxiill5py3ylzrbcs0j2hb\r\n
Accept-Encoding: gzip, deflate\r\n\r\n
'
b'
GET /favicon.ico HTTP/1.1\r\n
Host: 127.0.0.1:10086\r\n
Connection: keep-alive\r\n
Pragma: no-cache\r\n
Cache-Control: no-cache\r\n
User-Agent: Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/69.0.3497.100 Safari/537.36\r\n
Accept: image/webp,image/apng,image/*,*/*;q=0.8\r\n
Referer: http://127.0.0.1:10086/\r\nAccept-Language: zh-CN,zh;q=0.9\r\n
Cookie: csrftoken=VBVNk321AAGMuygu2OWoRXHUc2LiIspKoPaQfN1AbSY2WEUWPQS09ghoop1LzXFw; sessionid=os5tnm6lqwxxiill5py3ylzrbcs0j2hb\r\n
Accept-Encoding: gzip, deflate\r\n\r\n
'
咱們可使用decode對byte類型的數據進行加工。此處不作深刻,上述過程只爲了說明一點,web框架的本質就是byte類型的數據交互的過程。咱們能夠處理分析對方發過來的byte內容,而後處理後回覆不通類型的數據
上面咱們說到了web框架的本質,是處理b類型的數據和發送b類型的數據,在socket創建的狀況下。
可是,此時咱們須要明確,交互的數據有交互的規範。每種請求,不一樣狀態碼錶明的含義,包頭須要涵蓋的內容等,這些東西咱們都要去作處理分析。
這中間須要大量的人力投入,去開發一套穩定成熟的web框架。而此時,咱們須要在web框架上搭建的網站,平臺,系統等東西卻還都沒有開始開工。
如今市面上有大量成熟的web框架供咱們去使用,這裏就節省了咱們去開發web框架和專門研究交互報文的複雜過程。更快的投入入高效的開發
2.1 wsgivef.simple_server 的使用
瞭解了HTTP協議和HTML文檔,咱們其實就明白了一個Web應用的本質就是:
瀏覽器發送一個HTTP請求;
服務器收到請求,生成一個HTML文檔;
服務器把HTML文檔做爲HTTP響應的Body發送給瀏覽器;
瀏覽器收到HTTP響應,從HTTP Body取出HTML文檔並顯示。
因此,最簡單的Web應用就是先把HTML用文件保存好,用一個現成的HTTP服務器軟件,接收用戶請求,從文件中讀取HTML,返回。Apache、Nginx、Lighttpd等這些常見的靜態服務器就是幹這件事情的。
若是要動態生成HTML,就須要把上述步驟本身來實現。不過,接受HTTP請求、解析HTTP請求、發送HTTP響應都是苦力活,若是咱們本身來寫這些底層代碼,還沒開始寫動態HTML呢,就得花個把月去讀HTTP規範。
正確的作法是底層代碼由專門的服務器軟件實現,咱們用Python專一於生成HTML文檔。由於咱們不但願接觸到TCP鏈接、HTTP原始請求和響應格式,因此,須要一個統一的接口,讓咱們專心用Python編寫Web業務。
這個接口就是WSGI:Web Server Gateway Interface。
使用wsgi相比於上面的直接創建socket,wsgi省去了創建socket監聽端口這個過程
可是咱們在使用wsgi時候還須要去考慮http的返回值
from wsgiref.simple_server import make_server def xx(environ,start_response): #environ封裝全部客戶端發過來的信息 start_response('200 OK',[('Content-Type','text/html')]) return ['<h1>yes ok!</h1>'.encode('utf-8')] if __name__=='__main__': httpd=make_server('',8000,xx) print('start listen') httpd.serve_forever() 提高一 如何處理多個不一樣的url from wsgiref.simple_server import make_server def deal_index(): return ['<h1>index</h1>'.encode('utf-8')] def deal_login(): return ['<h1>login</h1>'.encode('utf-8')] def deal_register(): return ['<h1>register</h1>'.encode('utf-8')] url_dict={ '/index':deal_index, '/login':deal_login, '/register':deal_register } def deal_conn(environ,start_response): #environ封裝全部客戶端發過來的信息 start_response('200 OK',[('Content-Type','text/html')]) tmp_path=environ['PATH_INFO'] func=None if tmp_path in url_dict: func=url_dict[tmp_path] if func: return func() else: return ['<h1>404</h1>'.encode('utf-8')] if __name__=='__main__': httpd=make_server('',8000,deal_conn) print('start listen') httpd.serve_forever() 提高二 將頁面移出去->view中 ->頁面模板 將處理url的函數移出去放到->controller中 ->業務處理 將數據庫操做移動到->model中
咱們能夠根據發過來的 請求作相應的回覆,如200,400,500等
同時,爲了規範代碼咱們能夠將頁面移動到view中,數據庫操做移動到model中,url控制移動到controller中,
這樣 三個文件夾就組成了mvc架構
三、由wsgi模塊引出的mvc架構與mtv架構
從上文咱們知道
web框架本質->socket
wsgi->封裝socket->是咱們在編程時更專一於web,無需考慮socket,可是須要考慮返回值
wsgi中->規範三個文件夾 model,view,controller 組成mvc架構
同時,和mvc結構相似的有mtv架構 實際 model都是數據庫操做,template中存放頁面web,(相似於mvc中的v),view中存放url選路的操做(相似於mvc中的controller)
因爲wsgi中還須要咱們去考慮返回值等狀況,爲了更便於專一web的開發,減小http頭部返回值等信息的開發實際,
在python中又出現了再wsgi之上的封裝的web框架
Django:全能型Web框架;
web.py:一個小巧的Web框架;
Bottle:和Flask相似的Web框架;
Tornado:Facebook的開源異步Web框架。
uWSGI是一個Web服務器,它實現了WSGI協議、uwsgi、http等協議。Nginx中HttpUwsgiModule的做用是與uWSGI服務器進行交換。WSGI是一種Web服務器網關接口。它是一個Web服務器(如nginx,uWSGI等服務器)與web應用(如用Flask框架寫的程序)通訊的一種規範。
要注意 WSGI / uwsgi / uWSGI 這三個概念的區分。
WSGI是一種通訊協議。
uwsgi是一種線路協議而不是通訊協議,在此經常使用於在uWSGI服務器與其餘網絡服務器的數據通訊。
而uWSGI是實現了uwsgi和WSGI兩種協議的Web服務器。
綜上:wsgi處理socket,咱們還可使用uwsgi來和nginx進行對接處理高併發的狀況。在wsgi基礎上,爲了減小咱們對返回值,url路徑分析的處理時間,更高效的進行開發。在wsgi基礎上又出現了django,tornado,flask等框架。
1.1 命令行建立
#建立項目 D:\Python36\Scripts>django-admin.exe startproject myxxx #運行項目 D:\Python36\Scripts\myxxx>python manage.py runserver Performing system checks... System check identified no issues (0 silenced). You have 15 unapplied migration(s). Your project may not work properly until you apply the migrations for app(s): admin, auth, contenttypes, sessions. Run 'python manage.py migrate' to apply them. August 14, 2018 - 15:25:57 Django version 2.1, using settings 'myxxx.settings' Starting development server at http://127.0.0.1:8000/ Quit the server with CTRL-BREAK.
咱們在runserver的時候能夠指定ip和端口號 G:\mytest>python manage.py runserver 127.0.0.1:8888
1.2 pycharm建立
1.3 pycharm使用的一些注意點
新建django項目時報錯
django1.x 和django2.x的變化,實際變化不大。後面使用過程當中會有深刻理解
1.x的url與2.x的path及re_path
具體目錄的功能會在下文實際應用過程當中有更深入的理解
目錄結構 G:\MYTEST │ db.sqlite3 │ manage.py │ └─mytest │ settings.py │ urls.py │ wsgi.py │ __init__.py │ └─__pycache__ settings.cpython-36.pyc urls.cpython-36.pyc wsgi.cpython-36.pyc __init__.cpython-36.pyc G:\>
app至關於一個大項目的小模塊,一個大項目能夠有多個模塊組成,有不一樣的團隊負責開發。將每一個模塊分別獨立出來進行開發調試,能提升工做效率且便於項目的管理
3.1 app的建立
F:\django_test>python manage.py startapp CMDB
F:\django_test>python manage.py startapp openstack
3.2 app的目錄結構
3.3 文件功能
典型的一個mvc架構
models提供數據庫相關的操做
views用來對請求作處理,處理業務邏輯
templates用來存放web界面
4.1 經過HttpResponse
f=open('templates\login.html','rb') data=f.read() return HttpResponse(data)
4.2 經過render render的本質就是對HttpResponse的進一步封裝
from django.shortcuts import render return render(request,'login.html')
4.3 render的setting配置(目的告訴django你的templates在哪裏)
TEMPLATES = [ { 'BACKEND': 'django.template.backends.django.DjangoTemplates', 'DIRS':[os.path.join(BASE_DIR, 'templates'),], #添加這一句 'APP_DIRS': True,
4.4 redirect的本質
回覆302的報文,並添加Location字段,ajax對此302的redirect不作反應
對於web中要使用的靜態請求內容,通常不作views處理,將其配置成靜態文件來處理。即訪問這個url下的東西,直接是去獲取文件。
STATIC_URL = '/static/' STATICFILES_DIRS=( os.path.join(BASE_DIR,'static'), )
功能:打開url:xxx/login/ 顯示web,輸入用戶名密碼,若是不正確則報錯
6.1 urls 請求的解析
6.2 views 請求的處理、獲取請求內包含的內容
def login(request): if request.method=='POST': t_n=request.POST.get('name',None) t_p=request.POST.get('passwd',None) t_n=str(t_n) t_p=str(t_p) print(t_n) print(t_p) if t_n=='root' and t_p=='123': return redirect('/home/') else: return render(request, 'login.html',{'error_msg':'用戶名或密碼錯誤'}) return render(request,'login.html')
6.3 模板語言使用 渲染html文件並交給views返回
7.1 收到請求
7.2 路由系統urls 解析發送過來的請求
7.3 視圖函數 urls路由系統解析後,調用相應的視圖函數對請求進行處理
7.4 界面渲染 調用配置文件或request請求的內容,或數據庫內容,對web界面進行渲染,動態生成須要返回給用戶的界面的過程
7.5 返回用戶
#注意以上的請求生存週期只是簡單的歸納,後續在中間件環境還會對生存週期作相應的擴展。
1. 建立Django工程 django-admin startproject 工程名 2. 建立APP cd 工程名 python manage.py startapp cmdb 3、靜態文件 project.settings.py STATICFILES_DIRS = ( os.path.join(BASE_DIR, "static"), ) 4、模板路徑 DIRS ==> [os.path.join(BASE_DIR,'templates'),] 5、settings中 middlerware # 註釋 csrf 6、定義路由規則 url.py "login" --> 函數名 7、定義視圖函數 app下views.py def func(request): # request.method GET / POST # http://127.0.0.1:8009/home?nid=123&name=alex # request.GET.get('',None) # 獲取請求發來的而數據 # request.POST.get('',None) # return HttpResponse("字符串") # return render(request, "HTML模板的路徑") # return redirect('/只能填URL') -》從新請求到新地址 本地地址前面的/必須填 8、模板渲染(視圖函數) 特殊的模板語言 靜態文件->動態頁面
if request.method=='POST': if request.method=='GET':
request.path
request.path_info **經常使用
if request.method=='GET': print('GET',request.GET) print('POST',request.POST) ------------------------------- GET <QueryDict: {}> POST <QueryDict: {'question1': ['1-B', '1-C', '1-D']}> ------------------------------ request.GET.get('key') request.POST.get('key')
def home(request): if request.method=='POST': print('GET',request.GET) print('POST',request.POST) print('POSTLIST',request.POST.getlist('question1')) obj=request.POST.getlist('question1') for i in obj: print(i) return render(request, 'home.html') if request.method=='GET': print('GET',request.GET) print('POST',request.POST) return render(request,'home.html') GET <QueryDict: {}> POST <QueryDict: {'question1': ['1-B', '1-C', '1-D']}> POSTLIST ['1-B', '1-C', '1-D'] 1-B 1-C 1-D [15/Aug/2018 16:39:46] "POST /home/ HTTP/1.1" 200 968 #此處須要注意變量取出來的列表逐一輸出的方法和模板語言的寫法
5.1 獲取文件 x=request.Files.get()
5.2 獲取文件名 x.name
5.3 循環接收文件 chunks
def home(request): if request.method=='POST': tmp_file=request.FILES.get('test_paper') if tmp_file: f=open(tmp_file.name,'wb') for i in tmp_file.chunks(): f.write(i) f.close() for i in obj: print(i) return render(request, 'home.html')
6.1 FBV views中定義一個函數來處理請求 此處不作展開
6.2 CBV views中定義一個類來處理請求
6.3 urls中的調用
6.4 class的定義 繼承View
from django.views import View class Index(View): def get(self, req): print(‘method is :‘ + req.method) return render(req, ‘index.html‘) def post(self, req): print(‘method is :‘ + req.method) return render(req, ‘index.html‘) ----------------------------- urlpatterns = [ # url(r‘^index/‘, views.index), url(r‘^index/‘, views.Index.as_view()),
6.5 dispatch的使用 此方法在後面對界面作登陸檢測的時候會體現出裝飾器對cbv和fbv的區別
class cbv2(View): def dispatch(self, request, *args, **kwargs): print('before') t_return=super(cbv2, self).dispatch(request,*args,**kwargs) print('after') return t_return def get(self,request): return render(request,'home.html') def post(self,request): return HttpResponse('cbv post') Starting development server at http://127.0.0.1:8000/ Quit the server with CTRL-BREAK. before after
要區分{{ }}與{% %}
def func(request): return render(request, "index.html", {'current_user': "aaaa"}) --------------------------------------------------------------------- <html> <body> <div>{{current_user}}</div> </body> </html> ====> 最後生成的字符串 <html> <body> <div>aaaa</div> </body> </html>
def func(request): return render(request, "index.html", {'current_user': "alex", 'user_list': ['alex','eric']}) -------------------------------------------------------------------------------- <html> <body> <div>{{current_user}}</div> <ul> {% for row in user_list %} {% if row == "alex" %} <li>{{ row }}</li> {% endif %} {% endfor %} </ul> </body> </html>
經過下標取值
#####索引################# (傳入字典、列表取值的處理方法) def func(request): return render(request, "index.html", { 'current_user': "alex", 'user_list': ['alex','eric'], 'user_dict': {'k1': 'v1', 'k2': 'v2'}}) index.html <html> <body> <div>{{current_user}}</div> <a> {{ user_list.1 }} </a> <a> {{ user_dict.k1 }} </a> <a> {{ user_dict.k2 }} </a> </body> </html>
def func(request): return render(request, "index.html", { 'current_user': "alex", "age": 18, 'user_list': ['alex','eric'], 'user_dict': {'k1': 'v1', 'k2': 'v2'}}) index.html <html> <body> <div>{{current_user}}</div> <a> {{ user_list.1 }} </a> <a> {{ user_dict.k1 }} </a> <a> {{ user_dict.k2 }} </a> {% if age %} <a>有年齡</a> {% if age > 16 %} <a>老男人</a> {% else %} <a>小鮮肉</a> {% endif %} {% else %} <a>無年齡</a> {% endif %} </body> </html>
Html文件 {%for item in user_list%} <tr> <td>{{item.name}}</td> <td>{{item.sex}}</td> <td>{{item.email}}</td> </tr> {%endfor%} Views中 user_list=[ {'name':'a001', 'sex':'男','email':'a001@163.com'}, {'name':'a002', 'sex':'男','email':'a002@163.com'}, {'name':'a003', 'sex':'男','email':'a003@163.com'}, {'name':'a004', 'sex':'男','email':'a004@163.com'}, ] return render(request, 'home.html',{'user_list':user_list}) 字典處理 View中 user_dict={ 'k1':{'name': 'a001', 'sex': '男', 'email': 'a001@163.com'}, 'k2':{'name': 'a002', 'sex': '男', 'email': 'a002@163.com'}, 'k3':{'name': 'a003', 'sex': '男', 'email': 'a003@163.com'}, 'k4':{'name': 'a004', 'sex': '男', 'email': 'a004@163.com'}, } def deal_dict(request): return render(request,'dict.html',{'user_dict':user_dict}) Html中 <ul> {% for x in user_dict.keys %} <li>{{x}}</li> {% endfor %} <div>--------</div> {% for y in user_dict.values %} <li>{{y}}</li> {% endfor %} <div>--------</div> {% for z,zz in user_dict.items %} <li>{{z}}--{{zz}}</li> {% endfor %} </ul>
views
def detail(request): nid=request.GET.get('nid') return render(request,'detail.html',{'user_detail':user_dict[nid]}) dict頁面 {% for z,zz in user_dict.items %} <li><a href="/detail?nid={{z}}" target="_blank">{{zz.name}}</a></li> {% endfor %} Detail頁面 <body> <div>詳細信息</div> <div>姓名:{{user_detail.name}}</div> <div>性別:{{user_detail.sex}}</div> <div>郵箱:{{ user_detail.email }}</div> </body>
1.1 分組
urlpatterns = [ re_path('newdetail-(\d+)-(\d+).html', views.newdetail) ]
1.2 分組並指定變量名
re_path('newdetail-(?P<uid>\d+)-(?P<uuid>\d+).html', views.newdetail)
1.3 view中接收參數的方式
def newdetail(request,x1,x2):順序接收
def newdetail(request,nid,nnid):按變量名接收
def newdetail(request,*args,**kwargs):多變量接收
2.1 request.path_info
2.2 url name別名
2.2.1 肯定值
url中 re_path('namexxx',views.deal_name,name='tmp_name') Html中 <body> {%url 'tmp_name'%} </body>
2.2.2 搭配正則
<body> {%url 'tmp_name' 123 456%} </body>
2.3 reverse
此處不作描述,不常見,知道有這個方式便可
實際就是將總的項目文件夾中的urls拆分到各個app中的urls中
須要使用include
對象關係映射(英語:(Object Relational Mapping,簡稱ORM,或O/RM,或O/R mapping)
1.1 python manage.py makemigratations
1.2 python manage.py migrate
直接執行上面兩個指令,就能在項目的文件夾下發出現一個sqllite的文件,這就是django默認的數據庫了
2.1 setting中註冊
DATABASES = { 'default': { 'ENGINE': 'django.db.backends.mysql', 'NAME': 'django_1', 'HOST': '192.168.106.128', 'PORT': '3306', 'USER': 'root', 'PASSWORD': '123456', } }
2.2 init中註冊 注意要先安裝pymysql
import pymysql pymysql.install_as_MySQLdb()
3.1定義表
#在models中操做 from django.db import models class User_info(models.Model): name=models.CharField(max_length=32) passwd=models.CharField(max_length=64) class xxx(models.Model): name=models.CharField(max_length=32) passwd=models.CharField(max_length=64)
3.2 註冊表 在setting中
INSTALLED_APPS = [ 'django.contrib.admin', 'django.contrib.auth', 'django.contrib.contenttypes', 'django.contrib.sessions', 'django.contrib.messages', 'django.contrib.staticfiles', 'app1', ]
3.3執行生成表
3.3.1 python manage.py makemigratations
3.3.2 python manage.py migrate
D:\untitled>python manage.py makemigrations Migrations for 'app1': app1\migrations\0001_initial.py - Create model User_info - Create model xxx D:\untitled>python manage.py migrate
4.1 增長
3種新增記錄的方法 ->models.xxx.obj.create(k1=xxx,k2=xxx) ->models.xxx.obj.create(**xxx_dict) ->tmp_obj=models.xxx(k1=xxx,k2=xxx) tmp_obj.save()
4.2 查
4.2.1 全查 all()
4.2.2 過濾 filter() 過濾可使用q語句,在後面的項目中會具體展開
所有查 all 過濾 filter 一個條件 多個條件and關係 逗號 result=models.User_info.objects.all() for row in result: print(row.id,row.name,row.passwd) result1=models.User_info.objects.filter(name='xiaoming',passwd='aaaaaa') print('------分割線-----') for row in result1: print(row.id,row.name,row.passwd) return HttpResponse('orm') 1 tom 123456 2 alex abcdef 3 xiaoming aaaaaa 4 tom 123456 5 alex abcdef 6 xiaoming aaaaaa 7 tom 123456 8 alex abcdef 9 xiaoming aaaaaa ------分割線----- [17/Aug/2018 22:03:52] "GET /db_opt HTTP/1.1" 200 3 3 xiaoming aaaaaa 6 xiaoming aaaaaa 9 xiaoming aaaaaa
4.2.3 values 得到一個字典
4.2.4 values_list 得到一個列表
def db_search(request): s1=models.User_auth.objects.all() s2=models.User_auth.objects.all().values('name','password') s3=models.User_auth.objects.all().values_list('name','password') return render(request,'db_search.html',{'s1':s1,"s2":s2,"s3":s3}) --------------------------------------- <!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>Title</title> </head> <body> <p> <div>對象</div> <ul> {% for i in s1 %} <li>{{i.name}}-{{ i.password}}</li> {% endfor %} </ul> </p> <p> <div>字典</div> <ul> {% for i in s2 %} <li>{{i.name}}-{{ i.password}}</li> {% endfor %} </ul> </p> <p> <div>列表</div> <ul> {% for i in s3 %} <li>{{i.0}}-{{ i.1}}</li> {% endfor %} </ul> </p> </body> </html> -------------------------------
models.User.objects.filter(id=1,name='root') models.User.objects.filter(id__gt=1,name='root') models.User.objects.filter(id__lt=1) models.User.objects.filter(id__gte=1) models.User.objects.filter(id__lte=1)
4.2.5 get 沒有該值會報錯(能夠用try捕捉異常)
4.3 刪除 delete
models.User_info.objects.filter(name='xiaoming', passwd='aaaaaa').delete()
4.4 改 update
models.User_info.objects.filter(id=4).update(name=444,passwd=444)
4.5 一個實例,用戶信息管理
4.5.1 Html補充 Input 的 placeholder/a標籤的text-decoration: none;/ style="cursor: pointer"
用戶信息管理 from CMDB import models def init_db(request): # models.User_auth.objects.create(name='a001',password=123456) # models.User_auth.objects.create(name='a002', password='aaabbb') return render(request,'init_db.html') def c_login(request): if request.method=='POST': t_name=request.POST.get('name') t_passwd=request.POST.get('passwd') print(t_name,t_passwd) if (t_passwd and t_passwd): t_auth_result=models.User_auth.objects.filter(name=t_name,password=t_passwd).first() if t_auth_result: return redirect('/cmdb/c_index') else: return render(request, 'c_login.html', {'error_msg': '用戶名或密碼錯誤'}) else: return render(request,'c_login.html',{'error_msg':'不能爲空'}) return render(request,'c_login.html',{'error_msg':''}) def c_index(request): return render(request,'c_index.html') def c_user_manage(request): if request.method=="POST" : t_name=request.POST.get('name') t_password=request.POST.get('password') if t_name and t_password: models.User_auth.objects.create(name=t_name,password=t_password) return redirect('/cmdb/c_user_manage') else: pass else: pass t_sql_result=models.User_auth.objects.all() return render(request,'c_user_manage.html',{'user_info':t_sql_result}) def c_user_detail(request,nid): t_sql_result=models.User_auth.objects.filter(id=nid).first() return render(request, 'c_user_detail.html', {'user_detail': t_sql_result}) def c_user_del(request,nid): t_sql_result=models.User_auth.objects.filter(id=nid).delete() return redirect('/cmdb/c_user_manage') def c_user_edit(request,nid): if request.method=="POST": t_name=request.POST.get('name') t_pass=request.POST.get('password') if t_name and t_pass: models.User_auth.objects.filter(id=nid).update(name=t_name,password=t_pass) return redirect('/cmdb/c_user_manage') else: pass t_sql_result = models.User_auth.objects.filter(id=nid).first() return render(request,'c_user_edit.html',{'user_edit':t_sql_result})
5.1 增長列 (兩個思路)
5.1.1 給默認值
5.1.2 留空
5.2 刪除列 ->直接刪除
5.3 修改 ->直接修改
5.4 新建表
默認的自增id 注意自增和主鍵的區別,設置primary_key後就不會出現默認的id了
class User_test(models.Model): nid=models.CharField(max_length=32,primary_key=True) name=models.CharField(max_length=32) #AutoField(Field)
5.5 同步修改到數據庫
python manage.py makemigrations
python manage.py migrate
1.1 字符型
1.2 數字
1.3 時間
1.4 布爾值0/1
有些數據類型和字段參數非數據庫mysql自己的限制 而是djangoadmin中的限制
2.1 django admin的使用(帳號的創建)
要測試djangoadmin 此處須要創建超級用戶 (venv) F:\django_test>python manage.py createsuperuser Username (leave blank to use 'raytine'): root Email address: root@xxx.com Password: Password (again): This password is too short. It must contain at least 8 characters. This password is too common. This password is entirely numeric. Bypass password validation and create user anyway? [y/N]: y Superuser created successfully. (venv) F:\django_test>
另外還須要將自建的數據表註冊到djangoadmin中
from CMDB.models import User_test admin.site.register(User_test)
2.2 django中的數據類型
如下只列出幾個經常使用的
AutoField 用於存放 integer 類型的數字。 BooleanField 用於存放布爾類型的數據(Ture 或 False) CharField 用於存放字符型的數據,須要指定長度 max_length。 CommaSeparatedIntegerField 用於存放用逗號隔開的 integer 類型的數據。 DateField 日期型,必須是「YYYY-MM-DD」格式 DateTimeField 日期時間型,必須是"YYYY-MM-DD HH:MM[:ss[.uuuuuu]][TZ] "格式。 DecimalField 小數型,用於存放小數的數字。 EmailField 電子郵件類型 FilePathField 文件路徑類類型,FilePathFields must have either 'allow_files' or 'allow_folders' set to True. FloatField 浮點型。用於存放浮點型數據。 IntegerField 用於存放 integer 類型的數字。 BigIntegerField 用於存放大 integer 類型的數字,最大數支持:9223372036854775807 IPAddressField IP 地址類型,支持的 IPv4 的長度。 GenericIPAddressField 通常的 IP 地址,能夠支持ipv4和v6 TextField 用於存放文本類型的數據。 TimeField 時間類型。"HH:MM[:ss[.uuuuuu]]" 格式 URLField 用於存放 URL 地址
Django admin中會對一些char varchar類型的字符 作相應的限制 如是否知足ip email特徵這些。
2.3.1 null null=True 是否爲空
2.3.2 Default 默認值
2.3.3 Primary key 主鍵
2.3.4 db_column=’xxx’ 生成數據庫表時列的名字

2.3.5 db_index 建立普通索引
2.3.6 unique 惟一索引
2.3.7 幾種索引的理解

2.3.8 修改時間 auto_now 2.3.9 建立時間 auto_now_add 注意時間類型及修改時間生效的方式

obj=models.User_test.objects.get(name='test_update') obj.name='new_one' obj.save() 只能用get來修改才能生效
2.3.10 choice 將一部分信息放在內存中 屬於django的操做


2.3.11 Blank ->django admin中可否爲空 這個須要和數據庫 null作對比,一個是數據庫中的限制,一個是django中的限制
2.3.12 Editable ->django admin中可否被編輯 ,若是設置了不能被編輯 那麼這個字段就從admin界面隱藏
2.3.13 verbose_name -> django admin顯示字段中文
2.3.14 error_messages -> 錯誤信息
2.3.15 help_text -> django admin提示
2.3.16 validators -> django form ,自定義錯誤信息
dev_type=models.ForeignKey("devtype_table",to_field='tid',default=1,on_delete=models.
咱們在models中定義的字段名稱,若是是foreignkey字段,在數據庫中顯示的字段名實際爲fieldname_id,而直接的字段名,被用做表示對象
models.tb.object.create(name='root', user_group_id=1)
4,1 點獲取
4.2 values獲取,此方法要配合雙下劃線一塊兒使用
4.3 values_list,此方法一樣要配合雙下劃線一塊兒使用
a.b_obj.filedname
value_list('b_obj__fieldname')
在{% for %}循環內部,能夠訪問一個名爲forloop的模板變量。這個變量有若干屬性,經過它們能夠獲知循環進程的一些信息。 5.1 forloop.counter forloop.counter 的值是一個整數,表示循環的次數。這個屬性的值從 1 開始,所以第一次循環時,forloop.counter 等於 1 。 {% for item in todo_list %} <p>{{ forloop.counter }}: {{ item }}</p> {% endfor %}123 5.2 forloop.counter0 forloop.counter0 與 forloop.counter 相似,不過是從零開始的。第一次循環時,其值爲 0 。 5.3 forloop.revcounter forloop.revcounter的值是一個整數,表示循環中剩餘的元素數量。第一次循環時, forloop.revcounter 的值是序列中要遍歷的元素總數。最後一次循環時, forloop.revcounter的值爲 1 。 5.4 forloop.revcounter0 forloop.revcounter0 與 forloop.revcounter相似,不過索引是基於零的。第一次循環時, forloop.revcounter0的值是序列中元素數量減去一。最後一次循環時, forloop.revcounter0 的值爲 0 。 5.5 forloop.first forloop.first 是個布爾值,第一次循環時爲 True 。須要特殊處理第一個元素時很方便: {% for object in objects %} {% if forloop.first %} <li class="first"> {% else %} <li> {% endif %} {{ object }} </li> {% endfor %}123456789 5.6 forloop.last forloop.last是個布爾值,最後一次循環時爲True 。常常用它在一組連接之間放置管道符號: {% for link in links %} {{ link }}{% if not forloop.last %} | {% endif %} {% endfor %}
一、ajax的基本語法
$.ajax({ url: '/host', type: "POST", data: {'k1': 123,'k2': "root"}, success: function(data){ console.log(data) } })
二、ajax結合json的應用
$('#ajax_auth').click(function () { var t_ip=$('#top_add_dev_ip').val(); var t_port=$('#top_add_dev_port').val(); var t_type=$('#top_add_dev_type').val(); $.ajax({ url:'/ajax_auth', type:"POST", data:{'t_ip':t_ip,'t_port':t_port,'t_type':t_type}, //headers:{'X-CSRFtoken':$.cookie('csrftoken')}, //執行成功後自動執行此事件 success:function (r_data) { t_dict=JSON.parse(r_data); //JSON.stringify(t_dict) console.log(t_dict); if(t_dict['tag']===true){ location.reload(); }else { $('#top_error_info').text(t_dict['error']); } } }) }); -------------------------------------------- def ajax_edit_dev_info(requset): t_result = { 'tag' : True, 't_ip': None, 't_port': None, 't_type': None, } t_tag=requset.POST.get('tag') #print('---------》',json_data) #data=json.loads(json_data) t_did=requset.POST.get('did') if t_tag=='GET_DATA': result_dict=models.dev_info.objects.filter(did=t_did).values('did','dev_ip','dev_port','dev_type_id').first() t_result['did']=result_dict['did'] t_result['t_ip']=result_dict['dev_ip'] t_result['t_port'] = result_dict['dev_port'] t_result['t_type'] = result_dict['dev_type_id'] else: t_result['tag']=False return HttpResponse(json.dumps(t_result))
本身創建三張表,此方式比較靈活,各類功能能夠本身控制,只須要使用一對多foreginkey的知識點
class book(models.Model): id=models.AutoField(primary_key=True) book_name=models.CharField(max_length=64) class author(models.Model): id=models.AutoField(primary_key=True) author_name=models.CharField(max_length=64) class custom_book_and_author(models.Model): book_obj=models.ForeignKey(to='book',to_field='id',on_delete=models.CASCADE) author_obj=models.ForeignKey(to='author',to_field='id',on_delete=models.CASCADE)
此方法創建的多對多會自動生成第三張表,且咱們沒法經過程序直接操做第三張表,可是能夠經過兩個manytomany的對象來間接操做第三張表
class book(models.Model): id=models.AutoField(primary_key=True) book_name=models.CharField(max_length=64) class author(models.Model): id=models.AutoField(primary_key=True) author_name=models.CharField(max_length=64) r=models.ManyToManyField('book')#自動建立
方式一,自定義關係表的狀況下
可操做性空間大,但易用性比較麻煩
HostToApp.objects.create(hobj_id=1,aobj_id=2)
方式二 直接描述關係,間接操做第三張表,使用方便
obj = Application.objects.get(id=1) 增 obj.r.add(1) obj.r.add(2) obj.r.add(2,3,4) obj.r.add(*[1,2,3,4]) 刪 obj.r.remove(1) obj.r.remove(2,4) obj.r.remove(*[1,2,3]) 清空 obj.r.clear() 改 obj.r.set([3,5,7])
獲取queryset對象
obj.r.all()
obj.r.filter()
model -------------------------------------- class devtype_table(models.Model): tid=models.AutoField(primary_key=True) type_name=models.CharField(max_length=64) class dev_info(models.Model): did=models.AutoField(primary_key=True) dev_ip=models.CharField(max_length=32,unique=True) dev_port=models.CharField(max_length=32) dev_type=models.ForeignKey("devtype_table",to_field='tid',default=1,on_delete=models.CASCADE) -------------------------------------------- views --------------------------------------------- def c_dev_manage(request): dev_type_list=c_dev_select_list(request) if request.method=="POST" : t_ip=request.POST.get('dev_ip') t_port=request.POST.get('dev_port') t_type=request.POST.get('dev_type') print(t_ip,t_port,t_type) if t_ip and t_port and t_type: models.dev_info.objects.create(dev_ip=t_ip,dev_port=t_port,dev_type_id=t_type) return redirect('/cmdb/c_dev_manage') else: pass else: pass t_sql_result=models.dev_info.objects.all() return render(request,'c_dev_manage.html',{'dev_info':t_sql_result,'dev_type_list':dev_type_list,}) ---------------------------------------------- html ----------------------------------------------- <input type="button" class="m_button" value="添加"> <div id="top_login" class="top_login"> <div> <h3>設備添加</h3> <form action="/cmdb/c_dev_manage" method="POST"> <input type="text" placeholder="ip" name="dev_ip" id="top_add_dev_ip"> <input type="text" placeholder="post" name="dev_port" id="top_add_dev_port"> <select name="dev_type" id="top_add_dev_type"> <option value="1">路由器</option> <option value="2">交換機</option> <option value="3">防火牆</option> <option value="4">服務器</option> </select> <hr> <input id="top_add" type="submit" value="添加"> <input id="top_cancle" type="button" value="取消"> <a id="ajax_auth">ajax驗證</a> </form> <div id="top_error_info" style="color: red"></div> </div> </div> <div id="shadow" class="shadow"></div> ------------------------------------------------------- css ------------------------------------------------------- .hide{ display: none; } .item{ display: block; text-align: center; text-decoration: none; color: white; } .shadow{ position: fixed; top: 0; right: 0; left: 0; bottom: 0; background-color: black; opacity: 0.6; z-index: 101; } .top_login{ position: fixed; width: 500px; height: 300px; top:50%; left: 50%; margin-left: -250px; margin-top: -150px; background-color: gainsboro; z-index: 102; padding: 10px; } ------------------------------------------- js -------------------------------------------- obj_list=document.getElementsByClassName('m_button'); for(var i =0;i<obj_list.length;i++){ obj_list[i].onclick= function () { document.getElementById('shadow').classList.remove('hide'); document.getElementById('top_login').classList.remove('hide') }; } ------------------------------------- $.ajax({ url:'/ajax_auth', type:"POST", data:{'t_ip':t_ip,'t_port':t_port,'t_type':t_type}, //headers:{'X-CSRFtoken':$.cookie('csrftoken')}, //執行成功後自動執行此事件 success:function (r_data) { t_dict=JSON.parse(r_data); //JSON.stringify(t_dict) console.log(t_dict); if(t_dict['tag']===true){ location.reload(); }else { $('#top_error_info').text(t_dict['error']); } } }) --------------------------------------- ajax驗證 views def ajax_auth(request): t_result={ 'tag':True, 'error':None, 'data':None } t_ip=request.POST.get('t_ip') t_port=request.POST.get('t_port') t_type=request.POST.get('t_type') try: if t_ip and t_port and t_type: models.dev_info.objects.create(dev_ip=t_ip, dev_port=t_port, dev_type_id=t_type) else: t_result['tag']=False t_result['error']='輸入的格式不對' except Exception as err: t_result['tag'] = False t_err=str(err) t_result['error'] =t_err print(t_result) return HttpResponse(json.dumps(t_result))
重點是添加一個tag:mydid,以便後面編輯的時候調用
<a class="top_edit_label_a" mydid="3" style="cursor: pointer">模態編輯</a> #mydid 這一步是重點 ----------------------------- $('.top_edit_label_a').click( function () { var t_dict={ 'tag':'GET_DATA', 'did':null }; t_dict['did']=$(this).attr('mydid'); $('#shadow').removeClass('hide'); $('#top_edit').removeClass('hide'); console.log(t_dict); $.ajax({ url:'/ajax_edit_dev_info', type:'POST', data:t_dict, success:function (json_data) { data=JSON.parse(json_data); if (data['tag']){ $('#top_edit_dev_input_did').val(data['did']); $('#top_edit_dev_input_ip').val(data['t_ip']); $('#top_edit_dev_input_port').val(data['t_port']); $('#top_edit_dev_select_type').val(data['t_type']); }else{ location.reload(); } } }) } ); -------------------------------------- def ajax_edit_dev_info(requset): t_result = { 'tag' : True, 't_ip': None, 't_port': None, 't_type': None, } t_tag=requset.POST.get('tag') #print('---------》',json_data) #data=json.loads(json_data) t_did=requset.POST.get('did') if t_tag=='GET_DATA': result_dict=models.dev_info.objects.filter(did=t_did).values('did','dev_ip','dev_port','dev_type_id').first() t_result['did']=result_dict['did'] t_result['t_ip']=result_dict['dev_ip'] t_result['t_port'] = result_dict['dev_port'] t_result['t_type'] = result_dict['dev_type_id'] else: t_result['tag']=False return HttpResponse(json.dumps(t_result))
6.1 dateType:'JSON'
data=JSON.parse(json_data); #若是沒有指定dataTYPE而接收到的數據是json數據,則須要json.parse(data)來處理。
若是指定裏datatype爲json那麼,接收的data將被自動執行json.parse。
至關於datatype封裝了json.parse
$.ajax({ url:'', type:'POST', data:'', dataType:'JSON', success:function (json_data) { json_data['xxxx'] }
6.2 traditions:true
假如接收到的數據中字典內嵌套了列表,那麼ajax沒法解析,須要添加traditions:true來支持
6.3 serialize()
對於一個form,咱們能夠獲取到form 而後serialize()提交。簡便操做
不難發現,咱們不論獲取什麼信息如POST內容、GET內容、PATH路徑等都是從request中獲取,現有疑問,數據包交互的過程當中,包頭及包內還有不少其餘的內容,咱們如何去獲取呢,能從request中去獲取嗎,有三個方法可使用:request.environ/request.body/request.Meta
request.environ能夠獲取數據包內其餘的信息,包括django不會去處理的信息
django不會去處理request對象中全部的信息,它只幫咱們處理了一些較經常使用的POST、GET動做等,若是涉及到其餘關於數據包的操做,如獲取請求的UA時,咱們就須要去request.environ中本身去獲取了。
request.environ是一個字典,咱們經過for的方式查看內部全部的值,此處不展開了
set_cookie是放置在請求頭中的
response['k1']=v1
網頁的標題、導航欄等結構,在多個頁碼都會顯示,若是咱們在寫每一個界面的時候重複寫這些代碼,效率很低。因此將重複代碼作成模板,供其餘頁碼調用
extends用於導入網頁模板
{%extends 'test.html'%}
block用於定義代碼塊,即咱們須要在模板中規劃出相應的空白block,並給其命名,在調用模板的html文件中,咱們須要定義出有內容的block塊,頁面在渲染過程當中就會將這些block塊替換到模板的block塊位置。
須要注意普通內容的處理以及js、css內容的處理
導入模板 {%extends 'test.html'%} 普通內容content {% block content %} <div>填充到模板</div> {%endblock%} js與css的處理 {% block css %} .c1{ } {%endblock%} {% block js %} {%endblock%}
一個html文件只能引用一個模板即一個extends,不能引用多個
對於一些不少頁面都須要使用的小組件,咱們能夠將其單獨寫成一個html文件並使用include來調用
{% include 'tag.html' %}來使用
>base <body> base {% block content %} {% endblock %} </body> ->main {% extends 'xxx_base.html' %} {% block content %} <div>it is content</div> {% for i in t_dic %} {% include 'xxx_include.html' %} {% endfor %} {% endblock %} ->include <div>打開圖片www.{{ i }}.com</div> ----------------------------------------------------- base it is content 打開圖片www.1.com 打開圖片www.2.com 打開圖片www.3.com 打開圖片www.4.com 打開圖片www.5.com
django在模板渲染時將前端web界面內容返回到python中,使用python作處理後再返回給前端
django中自帶了一些filter處理前端的內容如
{{‘abc’|lower}} {{'<div>xxx</div>'|safe}}
咱們能夠本身定義這些方法來處理前端的內容
@register.simple_tag與load
->@register.simple_tag的使用 {%mysimpleTag k1 k2%}
->思路
a. app下建立templatetags目錄
b. 建立任意.py文件
c. 建立template對象
d. 裝飾器裝飾函數
@register.simple_tag
def func(a1,a2,a3....)
return "asdfasd"
e. settings中註冊APP
f. 頂部 {% load xxoo %}
g. {% 函數名 arg1 arg2 %}
h. 特殊狀況
TEMPLATES = [
{
'DIRS':[os.path.join(BASE_DIR, 'templates'),],
'libraries':{'local_simpletags': 'table_admin.templatetags.local_simpletags',}
},
]
缺點:
不能做爲if條件
優勢:
參數任意
->應用
->直接輸出返回結果
->賦值給一個變量
{% deal_str all_dict.o as x %}
{% if i == x %}
@register.filter與load
->filter
a. app下建立templatetags目錄
b. 任意xxoo.py文件
c. 建立template對象 register
d.
@register.filter
def func(a1,a2)
return "asdfasd"
e. settings中註冊APP
f. 頂部 {% load xxoo %}
g. {{ 參數1|函數名:"參數二,參數三" }} {{ 參數1|函數名:數字 }}
缺點:
最多兩個參數,不能加空格
優勢:
能做爲if條件
1.1 列表切片與queryset切片
x[0,10]
x[11,20]
x[21,30]
1.2 切片中變量的引入
x[y-1,y*10]
1.3 經過請求傳入變量的方法
將y這個變量賦值定義爲get內的一個參數
xxx.com/?y=1
2.1 divmod的使用
-> >>> divmod(10,2)
(5, 0)
>>> divmod(10,6)
(1, 4)
2.2 a標籤生成鏈接
總頁碼數=divmod(k1,k2)[0] 或 divmod(k1,k2)[0]+1 for i in range 生成 "<a herf='/?y=%s'>%s</a>"%(y,y)
2.3 xss攻擊的處理
{{ html_str|safe }}
-------------------------------
from django.utils.safestring import mark_safe
tmpstr=make_safr(tmpstr)
{% extends "mod_all.html" %} {% block css %} <style> .page_num{ margin:0 5px; text-align: center; padding: 2px; width: 30px; display: inline-block; border: 1px solid deepskyblue; } .page_num.active{ background-color: skyblue; } </style> {% endblock %} {% block content %} <ul> {% for i in record_list %} <li>{{i}}</li> {% endfor %} </ul> {{ html_str|safe }} {% endblock %} ------------------------- def paging(request): all_data_list=[] each_page_num=10 all_num_control=100 for i in range(1,all_num_control): all_data_list.append(i) all_data_len=len(all_data_list) totally_num,mod=divmod(all_data_len,each_page_num) if mod!=0: totally_num+=1 choice_page=int(request.GET.get('p',1)) start_no=(choice_page-1)*each_page_num end_no=start_no+each_page_num tmp_data_list=all_data_list[start_no:end_no] html_str=" " for i in range(1,totally_num+1): if i == choice_page: html_str +="<a href='/paging?p=%s' class='page_num active'>%s</a> "%(i,i) else: html_str += "<a href='/paging?p=%s' class='page_num'>%s</a> " % (i, i) html_str=mark_safe(html_str) return render(request,'paging.html',{'record_list':tmp_data_list,'html_str':html_str})
3.1 須要考慮的變量
->列表數量變量
->每頁顯示數量
->一次顯示多少頁碼
->當前頁
->前一頁、後一頁
->首頁、尾頁
3.2 須要考慮的狀況
->在頁碼充足的狀況下的顯示
->接近首頁
->接近尾頁
->總頁數少於一頁鎖展現的頁碼
class Page(object): def __init__(self,totally_page_num,choice_page,show_choice_page_no,path): #獲取變量 得到三個變量 self.totally_page_num = totally_page_num self.choice_page = choice_page self.show_choice_page_no = show_choice_page_no self.path=path @property def page_export(self): html_str = " " if self.choice_page == 1: html_prev_button = "<a href='%s?p=%s'>上一頁</a>" % (self.path,self.choice_page) html_next_button = "<a href='%s?p=%s'>下一頁</a>" % (self.path,self.choice_page + 1) elif self.choice_page == self.totally_page_num: html_prev_button = "<a href='%s?p=%s'>上一頁</a>" % (self.path,self.choice_page - 1) html_next_button = "<a href='%s?p=%s'>下一頁</a>" % (self.path,self.choice_page) else: html_prev_button = "<a href='%s?p=%s'>上一頁</a>" % (self.path,self.choice_page - 1) html_next_button = "<a href='%s?p=%s'>下一頁</a>" % (self.path,self.choice_page + 1) html_str += html_prev_button start_page_no = self.choice_page - self.show_choice_page_no end_page_no = self.choice_page + self.show_choice_page_no if start_page_no < 1: start_page_no = 1 end_page_no = 1 + self.show_choice_page_no + self.show_choice_page_no if end_page_no > self.totally_page_num: end_page_no = self.totally_page_num start_page_no = self.totally_page_num - self.show_choice_page_no - self.show_choice_page_no for i in range(start_page_no, end_page_no + 1): if i == self.choice_page: html_str += "<a href='%s?p=%s' class='page_num active'>%s</a> " % (self.path,i, i) else: html_str += "<a href='%s?p=%s' class='page_num'>%s</a> " % (self.path,i, i) html_str += html_next_button html_str = mark_safe(html_str) return html_str def paging(request): #part 1 初始化數據 all_data_list=[] all_num_control = 1000 for i in range(1,all_num_control): all_data_list.append(i) all_data_len = len(all_data_list) show_choice_page_no = 8 #初始化數據結束 #得到 #一、數據長度 all_data_len #二、總數據列表 all_data_list #part 1結束 # part2 # 定義每頁顯示的數據量 #計算總共須要多少頁 each_page_num=20 totally_page_num,mod=divmod(all_data_len,each_page_num) if mod!=0: totally_page_num+=1 #得到總共須要生成的頁數 # part2 結束 #part3 #須要得到用戶選定的頁碼 choice_page=int(request.GET.get('p',1)) #獲取到客戶選定的頁碼 #part 3結束 #part4 此時總頁碼數量,客戶選定的頁碼數量,總共要顯示的頁碼區間已經得到到了 #此時能夠根據上述的3個變量來生成分頁的 page_line_obj=Page(totally_page_num,choice_page,show_choice_page_no,'/paging') html_str=page_line_obj.page_export #part4 結束 html字符串生成 #爲了方便擴展,此處添加一個新變量叫path變量,簡單展現,不作擴展 #part5 生成當前頁的數據 start_data_no=(choice_page-1)*each_page_num end_data_no=start_data_no+each_page_num tmp_data_list=all_data_list[start_data_no:end_data_no] #part 6 返回客戶端界面 return render(request,'paging.html',{'record_list':tmp_data_list,'html_str':html_str})
cookie的本質就是服務器保存在瀏覽器的一些鍵值對,一些key對應一些value
2.1 設置cookie
t_res=render(request,'paging.html',) t_res.set_cookie('per_page_num',123) return t_res
2.2 獲取cookie
request.COOKIES.get('k1') request.COOKIES['k1']
login data.set_cookie('user_auth', t_u) return data index name=request.COOKIES.get('user_auth') return HttpResponse('welcome %s'%name)
4.1 設置cookie
data.set_cookie('k',v) #關閉瀏覽器即失效
4.2 獲取cookies(兩種方式)
request.COOKIES.get('k1') request.COOKIES['k1']
4.3 cookies的兩種時效設置
#方法一 max_age 單位s data.set_cookie('user_auth',t_u,max_age=10) #方法二 expires 設置時間 outtime_date=datetime.datetime.utcnow()+datetime.timedelta(hours=1) t_return_data.set_cookie('user_auth', t_u, expires=outtime_date) return t_return_data
4.4 httponly、domain、path、secure
httponly:httponly只容許http協議獲取cookie(document.cookie / $.cookie 經過js或jquery能獲取cookie)
domain : 生效的域名
path : 哪些頁面發送這個cookie
secure=True : https傳輸時候須要置爲True
思路 將max_age或expire設置爲當前時間(datetime.datetime.utcnow())便可
注意:和session對比,session的註銷能夠經過session.clear()來實現,可是cookie不行
7.1 jquery 與 jquerycookie的應用
jquery cookie是一個依賴於jquery的插件,須要單獨下載引入
$.cookie('k1','v1',{"path":'/paging'}) #三個部分,key、value、字典 #字典內包括了cookie能夠帶的那些參數,max_age/expire/httponly等
7.2 select框添加onchange事件
設置cookie $.cookie('per_pagenum':$(this).val())
添加location.reload(),使得配置的頁面當即生效
7.3 views函數返回
->獲取當前頁面 request.GET.get('p')
->獲取cookies中每頁顯示的數目 request.COOKIES.get()
->分頁函數處理
->已選擇的每頁顯示的select顯示指定的option
->$('select').val($.cookie('per_pagenum'))
7.4 完整代碼
{% block js %} <script src="/static/jquery-1.12.4.js"></script> <script src="/static/jquery.cookie.js"></script> <script> $('#per_page_num_select').val($.cookie('per_page_num')); $('#per_page_num_select').change( function () { $.cookie('per_page_num',$(this).val()); location.reload() } ) </script> {% endblock %} def paging(request): #part 1 初始化數據 val = request.COOKIES.get('per_page_num',30) print(val) all_data_list=[] all_num_control = 1000 for i in range(1,all_num_control): all_data_list.append(i) all_data_len = len(all_data_list) show_choice_page_no = 5 #初始化數據結束 #得到 #一、數據長度 all_data_len #二、總數據列表 all_data_list #part 1結束 # part2 # 定義每頁顯示的數據量 #計算總共須要多少頁 each_page_num=int(val) totally_page_num,mod=divmod(all_data_len,each_page_num) if mod!=0: totally_page_num+=1 #得到總共須要生成的頁數 # part2 結束 #part3 #須要得到用戶選定的頁碼 choice_page=int(request.GET.get('p',1)) #獲取到客戶選定的頁碼 #part 3結束 #part4 此時總頁碼數量,客戶選定的頁碼數量,總共要顯示的頁碼區間已經得到到了 #此時能夠根據上述的3個變量來生成分頁的 page_line_obj=Page(totally_page_num,choice_page,show_choice_page_no,'/paging') html_str=page_line_obj.page_export #part4 結束 html字符串生成 #爲了方便擴展,此處添加一個新變量叫path變量,簡單展現,不作擴展 #part5 生成當前頁的數據 start_data_no=(choice_page-1)*each_page_num end_data_no=start_data_no+each_page_num tmp_data_list=all_data_list[start_data_no:end_data_no] #part 6 返回客戶端界面 t_res=render(request,'paging.html',{'record_list':tmp_data_list,'html_str':html_str}) t_res.set_cookie('per_page_num',str(val)) return t_res
t_res.set_signed_cookie('per_page_num',str(val),salt='xxxx') request.get_signed_cookie('per_page_num',salt='xxxx')
9.1 fbv 自定義一個裝飾器便可
ef is_it_auth(fun): def inner(request,*args,**kwargs): t_u = request.COOKIES.get('user_auth') if t_u: t_result=fun(request) else: t_result=redirect('/lesson3/login') return t_result return inner @is_it_auth def l3_index(request): t_u = request.COOKIES.get('user_auth') return render(request,'l3_index.html',{'user_name':t_u,'user_detail':user_data[t_u]})
9.2 cbv的三種狀況及須要使用的django裝飾器
導入django裝飾器 ->from django.utils.decorators import method_decorator
9.2.1 針對單個動做作認證,如get,本身定義的函數還要通過method_decorator處理
from django.views import View from django.utils.decorators import method_decorator class testcbv(View): @method_decorator(is_it_auth) def get(self,request): t_u = request.COOKIES.get('user_auth') return render(request, 'l3_index.html', {'user_name': t_u, 'user_detail': user_data[t_u]}) def post(self,request): pass
9.2.2 針對全部動做的操做
裝飾dispatch函數
class testcbv(View): @method_decorator(is_it_auth) def dispatch(self, request, *args, **kwargs): t_return=super(testcbv,self).dispatch(request, *args, **kwargs)#繼承全部的方法 return t_return
9.2.3 針對類的裝飾器
@method_decorator(is_it_auth,dispatch) class TheOBJ(View)
不能包含敏感信息
2.1 保存在服務器端的鍵值對(字典)
2.2 session與cookie的關係
2.3 session必須依賴於cookie
2.4 服務器給客戶端一個cookie內部保存一個隨機字符串
2.5 服務器端保存此隨機字符串對應的相關信息
3.1 過程
3.1.1 生成隨機字符串
3.1.2 將隨機字符串返回給瀏覽器(經過cookie)
3.1.3 本地保存隨機字符串(默認保存在數據庫中)
3.1.4 給隨機字符串管理相應的字典保存數據
3.2 操做
django中將上述過程所有封裝,只須要執行一步指令便可
request.sesson['key']=value #設置值 x=request.session['key'] #取出值
def deal_session_login(request): if request.method=='POST': t_u=request.POST.get('name') t_p=request.POST.get('passwd') t_man=user_data.get(t_u) print(t_u,t_p) if not t_man or t_man['pwd']!=t_p: return render(request,'l3_deal_session_login.html',{"err_msg":'用戶名或密碼錯誤'}) if t_man['pwd']==t_p: request.session['name']=t_u request.session['is_login']=True t_return_data=redirect('/lesson3/deal_session_index') return t_return_data return render(request,'l3_deal_session_login.html') def deal_session_index(request): print('---begin') xxx=request.session.get('is_login') print('----',xxx) if xxx: return HttpResponse('welcome,%s'%request.session['name']) else: return redirect('/lesson3/deal_session_login')
5.1 獲取值
request.session.get('key',none)#獲取值 request.session['key']#若是key不存在會報錯
5.2 設置值
request.session.setdefault('key',value)#若是不存在,則設置,若是存在不改變 request.session['key']=123
5.3 刪除值
del request.session['key']
5.4 對字典的操做能夠運用在request.session上
request.session.keys() request.session.values() request.session.items()
5.5 獲取當前用戶的隨機字符串
request.sesson.session_key
5.6 刪除髒數據
request.session.clear_expired() #假如cookie被刪除,或過了超時時間,則會申請新的隨機字符串,那麼此時數據庫中將存在舊的字符串的髒數據,能夠經過此命令主動刪除
5.7 刪除整個session
request.session.delete(request.session.session_key) request.session.clear()#和上面功能同樣,可是不要去獲取隨機值
5.8 註銷的實現
原理即經過request.session.clear()來清除session完成註銷
5.9 註銷實例代碼
def deal_session_loginout(request): request.session.clear() return redirect('/lesson3/deal_session_login') <body> <h3>{{ user_name }}</h3> <h2>{{ user_detail.role }}</h2> </body>
5.10 session的超時時間
django默認的超時時間是兩週,這裏包括了數據庫的保存時間以及cookie的保存時間。
注意:session依賴於cookie,若是瀏覽器清空了cookie,那麼這個超時時間也就沒有意義了
5.11 session修改超時時間
5.11.1 全局的超時時間
在配置文件中配置
SESSION_COOKIE_AGE = 1209600 # Session的cookie失效日期(2周)(默認)
5.11.2 單用戶本身定義的超時時間
request.session.set_expiry(10)#單位是秒 #這個值能夠前端定義返回給後端
5.12 session的配置文件setting中配置
SESSION_COOKIE_NAME = "sessionid" # Session的cookie保存在瀏覽器上時的key,即:sessionid=隨機字符串(默認) SESSION_COOKIE_PATH = "/" # Session的cookie保存的路徑(默認) SESSION_COOKIE_DOMAIN = None # Session的cookie保存的域名(默認) SESSION_COOKIE_SECURE = False # 是否Https傳輸cookie(默認) SESSION_COOKIE_HTTPONLY = True # 是否Session的cookie只支持http傳輸(默認) SESSION_COOKIE_AGE = 1209600 # Session的cookie失效日期(2周)(默認) SESSION_EXPIRE_AT_BROWSER_CLOSE = False # 是否關閉瀏覽器使得Session過時(默認)#默認django中關閉瀏覽器不會清除cookies #若是這個設置爲True 則本地的cookies被清空 數據庫中的session也就失效了 cookies-age也就沒有用了 SESSION_SAVE_EVERY_REQUEST = False # 是否每次請求都保存Session,默認修改以後才保存(默認)
5.13 session配置中的重要的用法---SESSION_SAVE_EVERY_REQUEST
實例:SESSION_SAVE_EVERY_REQUEST和cookie結合實現10s無操做則退出
setting中 SESSION_SAVE_EVERY_REQUEST=True views中 -------------------- request.session.set_expiry(10) ---------------------- t_timeout=request.POST.get('settimeout',0) if t_timeout: request.session.set_expiry(10) #不斷刷新界面 則不退出,若是不刷新,則10s後超時
session能夠經過配置保存在不一樣的地方
->文件中
->數據庫中
->cache緩存中
->加密cookie中
->數據庫+緩存中(緩存沒有命中,則保存到數據庫)
能夠看看這位老哥寫的文章:https://www.cnblogs.com/phpstudy2015-6/p/6771239.html#_label2
總結就是一些涉及到錢的get或post動做,若是他人在第三方網站上嵌套了這類型的iframe,那麼你帶着你的cookie去訪問,則你帳戶的錢就丟失了
簡單的解決思路就是我給你一串隨機字符串,你在發送交易動做的時候帶上我給你的字符串,我知道是你主動訪問的
{%csrf_token%}
form中自動生成一個input框,將csrf_token隨着post動做發送給對端
3.1 只對此ajax生效的方法->設置X-CSRFtoken頭部
$.ajax( { url:'' method:'' data:{} headers:{'X-CSRFtoken':$.cookie('csrftoken')} success:function(data){} } )
3.2 對於全部ajax請求批量生效的方法->xhr.setRequestHeader
#AJAX 實例 XHR 請求 XMLHttpRequest 是 AJAX 的基礎 $.ajaxSetup( { beforeSend:function (xhr,settings) { xhr.setRequestHeader('X-CSRFtoken',$.cookie('csrftoken')); } } );
全局:
中間件 django.middleware.csrf.CsrfViewMiddleware
局部:
● @csrf_protect,爲當前函數強制設置防跨站請求僞造功能,即使settings中沒有設置全局中間件。
● @csrf_exempt,取消當前函數防跨站請求僞造功能,即使settings中設置了全局中間件。
注:from django.views.decorators.csrf import csrf_exempt,csrf_protect
中間件的本質就是一個類,註冊後的中間件,當請求來時會調用類中的方法在全局狀況下對全部的請求和回覆進行處理
->process_request(self,request) ->process_view(self,request,callback,callback_args,callback_kwargs) ->process_response(self,request,response) ->process_exception(select,request,exception) ->process_template_response
3.1 定義類
from django.utils.deprecation import MiddlewareMixin
class M1(MiddlewareMixin)
3.2 註冊中間件
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', ]
4.1 階段一 理解process_request(self,request)與process_response(self,request,response)
process_request(self,request)
->請求到達服務端,request先過此方法
->按中間件的註冊順序執行,即離views函數最遠的先執行
->若是無操做(無return),直接到達下一個中間件的process_request
->若是有返回值
->1.10之前版本給最靠近views的process_response作處理,依次返回
->1.10以後版本交給本身的process_response處理後依次返回,不會到最貼近views的那個response了
process_response(self,request,response)
->views函數處理完請求後,返回值會依次通過離views函數最近->離views函數最遠
->此方法須要return參數內的response或者本身定義的response
from django.utils.deprecation import MiddlewareMixin class M1(MiddlewareMixin): def process_request(self,request): print('m1-request') def process_response(self,request,response): print('m1-response') return response class M2(MiddlewareMixin): def process_request(self,request): print('m2-request') def process_response(self,request,response): print('m2-response') return response class M3(MiddlewareMixin): def process_request(self,request): print('m3-request') def process_response(self,request,response): print('m3-response') return response
4.2 基於process_request實現黑名單阻塞
class BlockedIpMiddleware(object): def process_request(self, request): if request.META['REMOTE_ADDR'] in getattr(settings, "BLOCKED_IPS", []): return http.HttpResponseForbidden('<h1>Forbidden</h1>')
4.3 階段二 理解process_view(self,request,callback,callback_args,callback_kwargs)
->此階段在畫圖的時候一般把它畫在urls路由系統以前
->可是從參數能夠看出實際上在process_request的基礎上,request.path_info內所帶的一些參數已經被處理過
->此方法和process_request同樣,不須要有返回值return
->若是有返回值,則講給本身的response以後按response的順序返回給客戶端(與process_request返回值的現象是一致,包括版本)
->此方法的執行順序是按註冊順序執行,即離views函數最遠的先執行
from django.utils.deprecation import MiddlewareMixin from django.shortcuts import HttpResponse class M1(MiddlewareMixin): def process_request(self,request): print('m1-request') def process_response(self,request,response): print('m1-response') return response def process_view(self, request, callback, callback_args, callback_kwargs): print('m1_view') class M2(MiddlewareMixin): def process_request(self,request): print('m2-request') def process_response(self,request,response): print('m2-response') return response def process_view(self, request, callback, callback_args, callback_kwargs): print('m2_view') class M3(MiddlewareMixin): def process_request(self,request): print('m3-request') def process_view(self, request, callback, callback_args, callback_kwargs): print('m3_view') def process_response(self,request,response): print('m3-response') return response
4.4 階段三 理解process_exception(select,request,exception)
->此方法爲處理異常的方法。若是沒有異常,則不處理
->若是有異常,按離views最近->最遠的順序一次執行
->若是沒有返回值,則執行下一個process_exception
->若是有返回值,直接交給離views最近的process_response處理(這個和process_request、process_view不一樣)
4.5 階段四 理解process_template_response
->運用場景少
->process_template_response方法的執行取決於視圖函數的返回的信息
->視圖函數若是使用render方法返回信息,中間件裏的process_template_response方法就會被執行.
4.6 概況有中間件的狀況下的整個生命週期
請求->process_requess->process_views->urls路由->views模板渲染,數據庫操做->process_template_response->process_exception->process_response
開發調試(實際就是什麼地方都不放)
內存
文件
數據庫
Memcache緩存(python-memcached模塊)
Memcache緩存(pylibmc模塊) 兩個能夠看作一個
將渲染好的html本地保存一份,以後瀏覽器發來的請求就直接回復保存的內容
緩存保存在文件中的配置 CACHES = { 'default': { 'BACKEND': 'django.core.cache.backends.filebased.FileBasedCache', 'LOCATION': os.path.join(BASE_DIR,'local_cache'), } }
4.1 單獨視圖函數加裝飾器,整個界面作緩存
-> from django.views.decorators.cache import cache_page @cache_page(10) 單位是秒
4.2 對頁面的某個部分作緩存
{%load cache%} #和自定義的simpletag有點像 {%cache 5000 k1%} 5000即秒,k1爲緩存的名稱 {%endcache%}
實例
{% load cache %} <!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>Title</title> </head> <body> {{t_time}}<hr /> {{t_time}}<hr /> {% cache 5 t_time %} {{t_time}}<hr /> {% endcache %} </body> </html>
4.3 對全部頁面作緩存
思路:中間件處理
django爲咱們準備好了兩個中間件
4.3.1 添加中間件的位置及兩個中間件的原理(爲何要有兩個)
->一個用來獲取最終的request請求,並和庫匹配,看看是否有緩存。若是存在,則直接返回緩存
->一個用來在離用戶最近的位置判斷,是否存在緩存,若是不存在,則寫入、
MIDDLEWARE = [ 'django.middleware.cache.UpdateCacheMiddleware', # 其餘中間件... 'django.middleware.cache.FetchFromCacheMiddleware', ]
按照請求週期來分析,若是先return了 那麼不會到達後面的函數
至關於django內部給咱們預留了鉤子進行操做
Model signals pre_init # django的modal執行其構造方法前,自動觸發 post_init # django的modal執行其構造方法後,自動觸發 pre_save # django的modal對象保存前,自動觸發 post_save # django的modal對象保存後,自動觸發 pre_delete # django的modal對象刪除前,自動觸發 post_delete # django的modal對象刪除後,自動觸發 m2m_changed # django的modal中使用m2m字段操做第三張表(add,remove,clear)先後,自動觸發 class_prepared # 程序啓動時,檢測已註冊的app中modal類,對於每個類,自動觸發 Management signals pre_migrate # 執行migrate命令前,自動觸發 post_migrate # 執行migrate命令後,自動觸發 Request/response signals request_started # 請求到來前,自動觸發 request_finished # 請求結束後,自動觸發 got_request_exception # 請求異常後,自動觸發 Test signals setting_changed # 使用test測試修改配置文件時,自動觸發 template_rendered # 使用test測試渲染模板時,自動觸發 Database Wrappers connection_created # 建立數據庫鏈接時,自動觸發
3.1 導入
from django.core.signals import request_finished from django.core.signals import request_started from django.core.signals import got_request_exception from django.db.models.signals import class_prepared from django.db.models.signals import pre_init, post_init from django.db.models.signals import pre_save, post_save from django.db.models.signals import pre_delete, post_delete from django.db.models.signals import m2m_changed from django.db.models.signals import pre_migrate, post_migrate from django.test.signals import setting_changed from django.test.signals import template_rendered from django.db.backends.signals import connection_created
3.2 註冊
3.3 __init__中使用
->定義信號
->註冊信號
->觸發信號
#定義 import django.dispatch access_web = django.dispatch.Signal(providing_args=["ip"]) #註冊 def record_access_web(*args,**kwargs): print('99999999999999999999999') print(args) print('00000000000000000000') print(kwargs) print('xxx') #觸發 access_web.connect(record_access_web)
1.1 form就是一個form,用來作數據驗證和生產html標籤
1.2 model用來提供數據庫表結構的定義,及表內容的增刪改查,及少許的數據驗證功能
1.3 form和model是兩個獨立的部分,在django中一般被結合在一塊兒使用,完成數據庫相關操做及數據驗證操做。
2.1 思路
2.1.1 定義一個類繼承forms.Form
2.1.2 定義字段
2.1.3 設置字段內的參數,完成數據驗證及html生成的相關配置(此處先不深究這些參數,先生成一個form再說)
from django.forms import fields,forms class MYForm(forms.Form): name=fields.CharField(max_length=32,min_length=8) pwd=fields.CharField() email=fields.EmailField(error_messages={'invalid':'格式錯誤'})
3.1 web界面發送數據POST
3.2 form接收數據並驗證數據
obj.is_valid() 返回True或False判斷是否符合格式
def fm(request): if request.method=="GET": return render(request,'fm.html') if request.method=="POST": obj=FM_AUTH(request.POST) t_result=obj.is_valid() return HttpResponse(t_result)
#注意此時form中的字段和input標籤的name要同樣,
4.1 obj.errors內保存了用戶全部的錯誤信息,信息保存的形式
{ ‘name’:[ValidationError] #'name':[{'code':xxx,'message':'errormsg'}] 能夠理解爲這種形式 ‘pwd’:[ValidationError] # ‘email’:[ValidationError] # }
4.2 批量輸出錯誤信息的幾種方式
->obj.errors 顯示爲ul li格式 <ul class="errorlist"> <li> name<ul class="errorlist"><li>Ensure this value has at least 8 characters (it has 4).</li></ul> </li> <li> email<ul class="errorlist"><li>Enter a valid email address.</li></ul> </li> </ul> ->obj.errors.as_json() 能顯示錯誤代碼code { "name": [{ "message": "Ensure this value has at least 8 characters (it has 4).", "code": "min_length" }], "email":[{ "message": "Enter a valid email address.", "code": "invalid" }] } ->obj.errors.as_p() 此處不展開 ->obj.errors.as_table()此處不展開 as_table 須要寫在<table></table>中
默認顯示的錯誤信息,咱們能夠修改
須要指定相應的code
定製方法是使用字段內的參數error_messages
pwd=forms.CharField(max_length=16,min_length=6,error_messages={'min_length':'過短','max_length':'太長'}) #error_messages內部字典的key就是as_json()時候的code
obj.errors['key'] --><ul class="errorlist"><li>Ensure this value has at least 8 characters (it has 4).</li></ul> obj.errors['key'][0] -->Ensure this value has at least 8 characters (it has 4). #模板語言
obj.errors.key.0
#
for i in obj:
i.errors.0
cleaned_data
#驗證成功後,數據被保存在cleaned_data中 是一個字典的格式 #cleaned_data能夠直接被插入數據庫 models.xxx.objects.create(**cleaned_data)
#自動生成input框,輸出錯誤信息(僅文字) {{obj.user}}{{obj.user.errors.0}} {{obj.pwd}}{{obj.pwd.errors.0}} {{obj.email}}{{obj.email.errors.0}} #保留原值 x=MYFORM(request.POST)
form自己只有數據驗證功能,生成html的功能是由widget插件來完成的
9.1 經過widget插件參數,及attrs參數
9.2 charFields是繼承Field,Field中定義了widget=TextInput
->class CharField(Field): def __init__(self, *, max_length=None, min_length=None, strip=True, empty_value='', **kwargs): ->class Field: widget = TextInput # Default widget to use when rendering this type of Field. ->class TextInput(Input): input_type = 'text' template_name = 'django/forms/widgets/text.html' -><input type="{{ widget.type }}" name="{{ widget.name }}" {% if widget.value != None %} value="{{ widget.value }}" {% endif %} {% include "django/forms/widgets/attrs.html" %}>
9.3 修改默認的插件
#給字段設置插件 widget=widgets.* from django.forms import widgets email=fields.EmailField(error_messages={'invalid':'格式錯誤'},widget=widgets.Textarea(attrs={'class':'c1','xxx':'xxx2'})) #設置樣式 attrs={'class':c1,'xxx':'xxx2'} #再來個例子 pwd=fields.CharField(max_length=16,min_length=6,error_messages={'min_length':'過短','max_length':'太長'},widget=widgets.PasswordInput())#不寫括號也能夠
Field required=True, 是否容許爲空 widget=None, HTML插件 label=None, 用於生成Label標籤或顯示內容 initial=None, 初始值 help_text='', 幫助信息(在標籤旁邊顯示) error_messages=None, 錯誤信息 {'required': '不能爲空', 'invalid': '格式錯誤'} show_hidden_initial=False, 是否在當前插件後面再加一個隱藏的且具備默認值的插件(可用於檢驗兩次輸入是否一直) validators=[], 自定義驗證規則 localize=False, 是否支持本地化 disabled=False, 是否能夠編輯 label_suffix=None Label內容後綴 CharField(Field) max_length=None, 最大長度 min_length=None, 最小長度 strip=True 是否移除用戶輸入空白 IntegerField(Field) max_value=None, 最大值 min_value=None, 最小值 FloatField(IntegerField) ... DecimalField(IntegerField) max_value=None, 最大值 min_value=None, 最小值 max_digits=None, 總長度 decimal_places=None, 小數位長度 BaseTemporalField(Field) input_formats=None 時間格式化 DateField(BaseTemporalField) 格式:2015-09-01 TimeField(BaseTemporalField) 格式:11:12 DateTimeField(BaseTemporalField)格式:2015-09-01 11:12 DurationField(Field) 時間間隔:%d %H:%M:%S.%f ... RegexField(CharField) regex, 自定製正則表達式 max_length=None, 最大長度 min_length=None, 最小長度 error_message=None, 忽略,錯誤信息使用 error_messages={'invalid': '...'} EmailField(CharField) ... FileField(Field) allow_empty_file=False 是否容許空文件 ImageField(FileField) ... 注:須要PIL模塊,pip3 install Pillow 以上兩個字典使用時,須要注意兩點: - form表單中 enctype="multipart/form-data" - view函數中 obj = MyForm(request.POST, request.FILES) URLField(Field) ... BooleanField(Field) ... NullBooleanField(BooleanField) ... ChoiceField(Field) ... choices=(), 選項,如:choices = ((0,'上海'),(1,'北京'),) required=True, 是否必填 widget=None, 插件,默認select插件 label=None, Label內容 initial=None, 初始值 help_text='', 幫助提示 ModelChoiceField(ChoiceField) ... django.forms.models.ModelChoiceField queryset, # 查詢數據庫中的數據 empty_label="---------", # 默認空顯示內容 to_field_name=None, # HTML中value的值對應的字段 limit_choices_to=None # ModelForm中對queryset二次篩選 ModelMultipleChoiceField(ModelChoiceField) ... django.forms.models.ModelMultipleChoiceField TypedChoiceField(ChoiceField) coerce = lambda val: val 對選中的值進行一次轉換 empty_value= '' 空值的默認值 MultipleChoiceField(ChoiceField) ... TypedMultipleChoiceField(MultipleChoiceField) coerce = lambda val: val 對選中的每個值進行一次轉換 empty_value= '' 空值的默認值 ComboField(Field) fields=() 使用多個驗證,以下:即驗證最大長度20,又驗證郵箱格式 fields.ComboField(fields=[fields.CharField(max_length=20), fields.EmailField(),]) MultiValueField(Field) PS: 抽象類,子類中能夠實現聚合多個字典去匹配一個值,要配合MultiWidget使用 SplitDateTimeField(MultiValueField) input_date_formats=None, 格式列表:['%Y--%m--%d', '%m%d/%Y', '%m/%d/%y'] input_time_formats=None 格式列表:['%H:%M:%S', '%H:%M:%S.%f', '%H:%M'] FilePathField(ChoiceField) 文件選項,目錄下文件顯示在頁面中 path, 文件夾路徑 match=None, 正則匹配 recursive=False, 遞歸下面的文件夾 allow_files=True, 容許文件 allow_folders=False, 容許文件夾 required=True, widget=None, label=None, initial=None, help_text='' GenericIPAddressField protocol='both', both,ipv4,ipv6支持的IP格式 unpack_ipv4=False 解析ipv4地址,若是是::ffff:192.0.2.1時候,可解析爲192.0.2.1, PS:protocol必須爲both才能啓用 SlugField(CharField) 數字,字母,下劃線,減號(連字符) ... UUIDField(CharField) uuid類型
required=True, 是否容許爲空 widget=None, HTML插件 label=None, 用於生成Label標籤或顯示內容 ->obj.user.label在生成html時,給input框等標籤以前添加說明 initial=None, 初始值
->initial={'user':123...} help_text='', 幫助信息(在標籤旁邊顯示) ->在後面的項目中有實例 error_messages=None, 錯誤信息 {'required': '不能爲空', 'invalid': '格式錯誤'} show_hidden_initial=False, 是否在當前插件後面再加一個隱藏的且具備默認值的插件(可用於檢驗兩次輸入是否一直) validators=[], 自定義驗證規則,可以使用正則表達式
disabled=False, 是否能夠編輯
12.1 實例1
username = fields.CharField( max_length=5, validators=[ RegexValidator( r'^[0-9]+$', 'Enter a valid extension.', 'invalid') ], )
12.2 實例2
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 PublishForm(Form): # 使用自定義驗證規則 phone = fields.CharField( validators=[mobile_validate, ], error_messages={'required': '手機不能爲空'}, widget=widgets.TextInput(attrs={'class': "form-control",'placeholder': u'手機號碼'}) )
咱們主要仍是使用CharField來進行定義
咱們能夠經過自定義正則的方式,來自行定義出不少django內部帶的或者是沒有帶的數據類型
參數allow_empty_file=False 是否容許空文件
14.1 正常使用常規的文件處理
def upload(request): if request.method=="GET": return render(request,'upload.html') if request.method=="POST": tmp_file_obj=request.FILES.get('uploadfile') if tmp_file_obj: f=open(tmp_file_obj.name,'wb') for i in tmp_file_obj.chunks(): f.write(i) f.close() return HttpResponse('ok') else: return HttpResponse('err') <body> <form action="/lesson3/upload" method="post" enctype="multipart/form-data"> <input type="file" name="uploadfile"> <input type="submit" value="upload"> </form> </body>
14.2 使用field.FileField()來處理文件
class UploadFile(forms.Form): uploadfile=fields.FileField(allow_empty_file=False) def upload_plus(request): if request.method=="GET": obj=UploadFile() return render(request,'upload_plus.html',{'obj':obj}) if request.method=="POST": obj=UploadFile(request.POST) if obj.is_valid(): fileobj=obj.cleaned_data['uploadfile'] f=open(fileobj.name,'wb') for i in fileobj.chunks(): f.write(i) f.close() return HttpResponse('ok') else: return HttpResponse('err') <body> <div>plus</div> <form action="/lesson3/upload" method="post" enctype="multipart/form-data"> {{ obj.uploadfile }} <input type="submit" value="上傳"> </form> </body>
15.1 單選下拉框
#使用choicesField ->choicesField(choices=[(1,上海),(2,廣州),(3,北京)],widget=widgets.Select) #使用CharField ->user = fields.CharField(initial=2,widget=widgets.Select(choices=((1,'上海'),(2,'北京'),)))
15.2 多選的下拉框
MultipleChoiceField(choices=((1,上海),(2,廣州),(3,北京))#列表/元組均可以
15.3 單選的radio處理
#使用charField user = fields.CharField( initial=2, widget=widgets.RadioSelect(choices=((1,'上海'),(2,'北京'),)) ) #使用ChoiceField user = fields.ChoiceField( choices=((1, '上海'), (2, '北京'),), initial=2, widget=widgets.RadioSelect )
15.4 單選的checkbox處理
user = fields.CharField(widget=widgets.CheckboxInput())
15.5 多選checkbox,值爲列表
user = fields.MultipleChoiceField( initial=[2, ], choices=((1, '上海'), (2, '北京'),), widget=widgets.CheckboxSelectMultiple )
from django.forms import widgets class Man(forms.Form): name=fields.CharField(max_length=12,min_length=1,label='name') pwd=fields.CharField(max_length=12,min_length=6,label='密碼',widget=widgets.PasswordInput(attrs={'class':'c1','xxx':'999'})) email=fields.EmailField() sex=fields.ChoiceField( choices=((1,'男'),(2,'女')), widget=widgets.RadioSelect, label='sex', ) city=fields.ChoiceField( choices=((1,'北'),(2,'上'),(3,'廣'),(4,'深')), widget=widgets.Select, label='city' ) hobit=fields.MultipleChoiceField( choices=((1, '吃'), (2, '喝'), (3, '睡覺'), (4, '打醬油'),), widget=widgets.CheckboxSelectMultiple, label='hobit', ) agree=fields.ChoiceField( widget=widgets.CheckboxInput, label='我贊成此協議', ) def select(request): if request.method=="GET": obj=Man() return render(request,'select.html',{'obj':obj}) if request.method=="POST": obj=Man(request.POST) obj.is_valid() x=obj.cleaned_data print(x) return HttpResponse('ok!') <body> <form method="post"> <div>{{ obj.name.label }}{{ obj.name }}</div> <div>{{ obj.pwd.label }}{{ obj.pwd }}</div> <div>{{ obj.email.label }}{{ obj.email }}</div> <div>{{ obj.sex.label }}{{ obj.sex }}</div> <div>{{ obj.hobit.label }}{{ obj.hobit }}</div> <div>{{ obj.agree.label }}{{ obj.agree }}</div> <input type="submit" value="submit"> </form> </body>
initial初始化字段
username = fields.CharField(max_length=32,initial=123)
使用字典初始話form界面生成的html則帶有內容
class MYForm(forms.Form): username = fields.CharField(max_length=32,initial=123) email = fields.EmailField() choices=[] usertype_id = fields.ChoiceField(label='用戶類型',choices=choices) def __init__(self,*args,**kwargs): x=super(MYForm, self).__init__(*args,**kwargs) self.fields['usertype_id'].choices = models.UserType.objects.all().values_list() return x def login(request): t_data=models.UserInfo.objects.filter(id=2).first() t_data_dict=t_data.__dict__ t_dict={} obj=MYForm(t_data_dict) return render(request,'123.html',{'obj':obj})
Html補充 Input 的 placeholder 與 a標籤的 text-decoration: none; 與 style="cursor: pointer" django基本操做 ->簡介 ->django版本 ->建立project ->方式一 經過django-admin.exe建立 ->django-admin.exe startproject projectnamexxx ->python manage.py runserver 測試 ->方式二 經過pycharm來建立 ->new django project(圖形化) ->packaging_tool.py 修改方式 ->django的目錄結構 ->manage.py ->python manage.py runserver 127.0.0.1:8888 ->python manage.py startapp xxx ->python manage.py makemigrations ->python manage.py migrate ->db.sqllite3 ->setting.py ->urls.py ->wsgi.py ->__init__.py ->實例:添加一個url,返回HttpResponse ->創建app ->app的概念 ->建立app ->manag.py startapp xxx ->功能下發到views中 ->url的修改 ->app的目錄結構 ->migrations ->admin ->apps ->models ->test ->views ->實例一:訪問web打開一個web界面 ->方法一:Httpresponse ->方法二:render ->須要配置DIRS ->靜態請求的配置(css js jquery文件的位置) ->實例二:驗證密碼,正確跳轉,錯誤界面提示 ->redirect ->模板語言 ->django請求的生命週期 ->收到請求 ->路由系統 ->視圖函數 ->界面模板 ->界面渲染(模板語言、數據庫models操做) ->返回用戶 ->獲取內容 ->method ->get.get/post.get ->get.getlist/post.getlist/post ->上傳文件 Files.get ->name ->chunks ->fbv與cbv —>模板語言 ->變量 ->列表的下標 ->字典的下標 ->循環 ->循環列表 ->循環字典 ->條件 ->實例 查看詳情 ->re_path正則表達式的使用 ->(\d+) (\w+) ->分組 (?P<nid>\d+) ->views中接收參數的方式 ->*args/**kwargs(多參數狀況) ->順序 ->變量名(分組的狀況下)
->templates中生成url的方法 ->reverse 生成url的方法 ->request.path_info
->urls
->多變量狀況 ->urls 路由分發 include ->django對數據庫的操做 ->鏈接mysql ->鏈接mysql的基本設置 ->app註冊 ->定義單表 ->生成表 ->makemigrations/migrate ->migrations文件夾下操做記錄的刪除 ->ORM概念 ->單表的增刪改查 ->增 ->3種新增記錄的方法 ->models.xxx.obj.create(k1=xxx,k2=xxx) ->models.xxx.obj.create(**xxx_dict) ->tmp_obj=models.xxx(k1=xxx,k2=xxx) tmp_obj.save() ->查 ->全查 ->過濾 ->單個過濾條件 ->多個過濾條件 ->values ->vlaues_list ->get ->容易出錯 ->刪除 ->delete ->改 ->update ->實例:用戶信息管理 ->數據表結構的修改 ->增長列 ->給默認值 ->留空 ->刪除列 ->直接刪除 ->修改 ->直接修改 ->新建表 ->默認的自增id ->表的數據類型及字段參數 ->數據類型 ->django admin的使用(帳號的創建) ->整數/長整數/浮點數 ->二進制數 ->字符型 ->日期型 ->自增 ->django自有的email、ip類型等 ->參數類型 ->null ->default ->primary key ->db_column ->db_index ->unique ->幾種索引的理解 ->auto_now ->auto_now_add ->注意時間類型及修改時間生效的方式 ->choice ->blank ->editable ->verbose_name -> django admin顯示字段中文 ->error_messages -> 錯誤信息欠 ->help_text -> django admin提示 ->validators -> django form ,自定義錯誤信息(欠) ->一對多操做 ->如何創建外鍵
->外鍵字段再數據庫中的保存形式_id
->一對多的狀況下如何添加數據
->一對多的狀況下如何獲取數據
_id
多對多操做 ajax
補充url的命名空間
->request對象所包含的信息 不難發現,咱們不論獲取什麼信息如POST內容、GET內容、PATH路徑等都是從request中獲取,現有疑問,數據包交互的過程當中,包頭及包內還有不少其餘的內容,咱們如何去獲取呢,能從request中去獲取嗎 ->request.environ 獲取數據包內其餘的信息 ->django不會去處理request對象中全部的信息,它只幫咱們處理了一些較經常使用的POST、GET動做等,若是涉及到其餘關於數據包的操做,如獲取請求的UA時,咱們就須要去request.environ中本身去獲取了。 ->request.environ是一個字典,咱們經過for的方式查看內部全部的值,此處不展開了 ->模板處理 ->{%extends 'test.html'%}與block ->普通內容content ->{% block content %} ->js與css的處理 ->{% block css %} ->{% block js %} ->include ->一個html文件只能引用一個模板即一個extends,不能引用多個 ->對於一些不少頁面都須要使用的小組件,咱們能夠將其單獨寫成一個html文件並使用include來調用 ->{% include 'tag.html' %}來使用 {% extends 'xxx_base.html' %} ->例子 ->base <body> base {% block content %} {% endblock %} </body> ->main {% block content %} <div>it is content</div> {% for i in t_dic %} {% include 'xxx_include.html' %} {% endfor %} {% endblock %} ->include <div>打開圖片www.{{ i }}.com</div> ->效果 base it is content 打開圖片www.1.com 打開圖片www.2.com 打開圖片www.3.com 打開圖片www.4.com 打開圖片www.5.com ->自定義tag與filter 至關於經過某種方式將前端web界面內容返回到python中,使用python作處理後再返回給前端 ->@register.simple_tag的使用 {%mysimpleTag k1 k2%} ->思路 a. app下建立templatetags目錄 b. 建立任意.py文件 c. 建立template對象 d. 裝飾器裝飾函數 @register.simple_tag def func(a1,a2,a3....) return "asdfasd" e. settings中註冊APP f. 頂部 {% load xxoo %} g. {% 函數名 arg1 arg2 %} h. 特殊狀況 TEMPLATES = [ { 'DIRS':[os.path.join(BASE_DIR, 'templates'),], 'libraries':{'local_simpletags': 'table_admin.templatetags.local_simpletags',} }, ] 缺點: 不能做爲if條件 優勢: 參數任意 ->應用 ->直接輸出返回結果 ->賦值給一個變量 {% deal_str all_dict.o as x %} {% if i == x %} ->filter a. app下建立templatetags目錄 b. 任意xxoo.py文件 c. 建立template對象 register d. @register.filter def func(a1,a2) return "asdfasd" e. settings中註冊APP f. 頂部 {% load xxoo %} g. {{ 參數1|函數名:"參數二,參數三" }} {{ 參數1|函數名:數字 }} 缺點: 最多兩個參數,不能加空格 優勢: 能做爲if條件 ->分頁功能的實現 ->階段一 原理 ->列表切片 ->x[0,10] ->x[11,20] ->變量引入 ->x[y-1,y*10] ->將y這個變量賦值定義爲get內的一個參數 ->xxx.com/?y=1 ->階段二 基本實現 ->divmod的使用 -> >>> divmod(10,2) (5, 0) >>> divmod(10,6) (1, 4) ->a標籤生成鏈接 -> "<a herf='/?y=%s'>%s</a>"%(y,y) -> 總頁碼數=divmod(k1,k2)[0] 或 divmod(k1,k2)[0]+1 -> for i in range 生成 ->xss攻擊的處理 ->{{ html_str|safe }} -> from django.utils.safestring import mark_safe tmpstr=make_safr(tmpstr) ->階段三 引入變量作成標準模塊 ->須要考慮的變量 ->列表數量變量 ->每頁顯示數量 ->一次顯示多少頁碼 ->當前頁 ->前一頁、後一頁 ->首頁、尾頁 ->須要考慮的狀況 ->在頁碼充足的狀況下的顯示 ->接近首頁 ->接近尾頁 ->總頁數少於一頁鎖展現的頁碼 ->實例 ->cookies ->cookie是什麼 本質 ->cookie簡單實現用戶登陸 ->cookie的參數 ->設置cookie ->set_cookie('k',v) #關閉瀏覽器即失效 ->獲取cookies ->request.COOKIES.get('k1') ->request.COOKIES['k1'] ->cookies的兩種時間設置 ->data.set_cookie('user_auth',t_u,max_age=10) ->outtime_date=datetime.datetime.utcnow()+datetime.timedelta(hours=1) t_return_data.set_cookie('user_auth', t_u, expires=outtime_date) return t_return_data ->cookies的一些參數 主要仍是時間有關的參數 ->max_age ->expires ->httponly ->document.cookie / $.cookie 經過js或jquery能獲取cookie ->httponly只容許http協議獲取cookie ->domain 生效的域名 ->path 是不是全部頁面都發送這個cookie ->secure=False https傳輸 ->cookie在瀏覽器中的查看(有道筆記圖) ->cookie實現註銷 ->思路 將max_age或expire設置爲當前時間便可 ->cookie實現分頁定製的操做 ->jquery 與 jquery cookie的應用 ->$.cookie('k1','v1',{"path":'/paging'}) ->三個部分,key、value、字典 ->字典內包括了cookie能夠帶的那些參數,max_age/expire/httponly等 ->select框添加onchange事件 ->設置cookie $.cookie('per_pagenum':$(this).val()) ->添加location.reload()設置完成後當即生效 ->views函數的處理 ->獲取當前頁面 request.GET.get('p') ->獲取cookies中沒有顯示的數目 request.COOKIES.get() ->分頁函數處理 ->已選擇的每頁顯示的select顯示指定的option ->$('select').val($.cookie('per_pagenum')) ->完整代碼 ->cookie的加密salt ->t_res.set_signed_cookie('per_page_num',str(val),salt='xxxx') ->request.get_signed_cookie('per_page_num',salt='xxxx') ->使用cookie實現認證 裝飾器版 ->fbv 自定義一個裝飾器便可 ->cbv的三種狀況及須要使用的django裝飾器 ->導入django裝飾器 ->from django.utils.decorators import method_decorator ->針對單獨動做的裝飾,如get -> @method_decorator(is_it_auth) def get(self,request): ->針對全部動做的操做 ->裝飾dispatch函數 ->寫一個dispatch ->return super(THEOBJ,self).dispatch(request,*args,**kwargs) -> @method_decorator(is_it_auth) def dispatch(self,request): ->針對類的裝飾器 @@method_decorator(is_it_auth,dispatch) class TheOBJ(View) ->request的補充 ->request.Meta ->請求頭 ->request.body ->請求內容 ->request.environ ->處理後的一個請求的大字典 ->set_cookie是放置在請求頭中的 ->響應頭添加自定義字段的方法 ->response['k1']=v1 ->model中的反向查找的方法 ->關聯表名b_set ->session ->cookie的缺點及注意事項 ->不能包含敏感信息 ->session的本質 ->保存在服務器端的鍵值對(字典) ->session與cookie的關係 ->session必須依賴於cookie ->服務器給客戶端一個cookie內部保存一個隨機字符串 ->服務器端保存此隨機字符串對應的相關信息 ->session完成用戶登陸 ->過程 ->生成隨機字符串 ->將隨機字符串返回給瀏覽器(經過cookie) ->本地保存隨機字符串(默認保存在數據庫中) ->給隨機字符串管理相應的字典保存數據 ->操做 ->django中將上述過程所有封裝,只須要執行一步指令便可 ->request.sesson['key']=value 設置值 ->x=request.session['key'] 取出值 ->用戶登陸認證明例 ->有道筆記代碼 ->session的方法及參數 ->獲取值 ->request.session.get('key',none)獲取值,此方法request.session['key']若是key不存在會報錯 ->設置值 ->request.session.setdefault('key',value)若是不存在,則設置,若是存在不改變 ->request.session['key'] ->刪除值 ->del request.session['key'] ->對字典的操做能夠運用在request.session上 ->request.session.keys() ->request.session.values() ->request.session.items() ->獲取當前用戶的隨機字符串 ->request.sesson.session_key ->刪除髒數據 ->request.session.clear_expired() ->假如cookie被刪除,或過了超時時間,則會申請新的隨機字符串,那麼此時數據庫中將存在舊的字符串的髒數據,能夠經過此命令主動刪除 ->刪除整個session ->request.session.delete(request.session.session_key) ->request.session.clear()和上面功能同樣,可是不要去獲取隨機值 ->註銷使用 ->註銷實例代碼 -> def deal_session_loginout(request): request.session.clear() return redirect('/lesson3/deal_session_login') ->圖片 有道雲 補充 ->session的超時時間 ->django默認的超時時間是兩週 ->數據庫保存時間 ->cookie的有效時間 ->須要考慮的狀況 ->全局的超時時間 ->在配置文件中配置 ->單用戶本身定義的超時時間 ->界面設置checkbox或select,後端讀取後 ->request.session.set_expiry(10)單位是秒 ->session的配置文件setting中配置 ->SESSION_COOKIE_NAME = "sessionid" # Session的cookie保存在瀏覽器上時的key,即:sessionid=隨機字符串(默認) SESSION_COOKIE_PATH = "/" # Session的cookie保存的路徑(默認) SESSION_COOKIE_DOMAIN = None # Session的cookie保存的域名(默認) SESSION_COOKIE_SECURE = False # 是否Https傳輸cookie(默認) SESSION_COOKIE_HTTPONLY = True # 是否Session的cookie只支持http傳輸(默認) SESSION_COOKIE_AGE = 1209600 # Session的cookie失效日期(2周)(默認) SESSION_EXPIRE_AT_BROWSER_CLOSE = False # 是否關閉瀏覽器使得Session過時(默認)#默認django中關閉瀏覽器不會清除cookies 若是這個設置爲True 則本地的cookies被清空 數據庫中的session也就失效了 cookies-age也就沒有用了 SESSION_SAVE_EVERY_REQUEST = False # 是否每次請求都保存Session,默認修改以後才保存(默認) ->重要的用法是SESSION_SAVE_EVERY_REQUEST ->SESSION_SAVE_EVERY_REQUEST和cookie結合實現10s無操做則退出 ->SESSION_SAVE_EVERY_REQUEST=True ->request.session.set_expiry(10) ->t_timeout=request.POST.get('settimeout',0) if t_timeout: request.session.set_expiry(10) ->一張實例截圖 ->session能夠保存的位置 ->session能夠經過配置保存在不一樣的地方 ->文件中 ->數據庫中 ->cache緩存中 ->加密cookie中 ->數據庫+緩存中(緩存沒有命中,則保存到數據庫) ->CSRF ->csrf原理 ->https://www.cnblogs.com/phpstudy2015-6/p/6771239.html#_label2 總結就是一些涉及到錢的get或post動做,若是他人在第三方網站上嵌套了這類型的iframe,那麼你帶着你的cookie去訪問,則你帳戶的錢就丟失了 ->簡單的解決思路就是我給你一串隨機字符串,你在發送交易動做的時候帶上我給你的字符串,我知道是你主動訪問的 ->form的csrf提交方式 ->{%csrf_token%} ->ajax的處理方式(兩種) ->只讀此ajax生效 $.ajax( { url:'' method:'' data:{} headers:{'X-CSRFtoken':$.cookie('csrftoken')} success:function(data){} } ) ->批量生效 AJAX 實例 XHR 請求 XMLHttpRequest 是 AJAX 的基礎 $.ajaxSetup( { beforeSend:function (xhr,settings) { xhr.setRequestHeader('X-CSRFtoken',$.cookie('csrftoken')); } } ); ->中間件 中間件的本質就是一個類,註冊後的中間件,當請求來時會調用類中的方法在全局狀況下對全部的請求和回覆進行處理 ->中間件中的5個方法 ->process_request(self,request) ->process_view(self,request,callback,callback_args,callback_kwargs) ->process_response(self,request,response) ->process_exception(select,request,exception) ->process_template_response ->定義中間件的方法 ->from django.utils.deprecation import MiddlewareMixin class M1(MiddlewareMixin) ->中間件的註冊 ->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', ] ->中間件中方法的理解 ->階段一 理解process_request(self,request)與process_response(self,request,response) process_request(self,request) ->請求到達服務端,request先過此方法 ->按中間件的註冊順序執行,即離views函數最遠的先執行 ->若是無操做,直接到達下一個中間件的process_request ->若是有返回值 ->1.10之前版本給最靠近views的process_response作處理,依次返回 ->1.10以後版本交給本身的process_response處理後依次返回,不會到最貼近views的那個response了 process_response(self,request,response) ->views函數處理完請求後,返回值會依次通過離views函數最近->離views函數最遠 ->此方法須要return參數內的response或者本身定義的response ->有道雲圖片 ->基於process_request實現黑名單阻塞 class BlockedIpMiddleware(object): def process_request(self, request): if request.META['REMOTE_ADDR'] in getattr(settings, "BLOCKED_IPS", []): return http.HttpResponseForbidden('<h1>Forbidden</h1>') ->階段二 理解process_view(self,request,callback,callback_args,callback_kwargs) ->此階段在畫圖的時候一般把它畫在urls路由系統以前 ->可是從參數能夠看出實際上在process_request的基礎上,request.path_info內所帶的一些參數已經被處理過 ->此方法和process_request同樣,不須要有返回值return ->若是有返回值,則講給本身的response以後按response的順序返回給客戶端(與process_request返回值的現象是一致,包括版本) ->此方法的執行順序是按註冊順序執行,即離views函數最遠的先執行 ->階段三 理解process_exception(select,request,exception) ->此方法爲處理異常的方法。若是沒有異常,則不處理 ->若是有異常,按離views最近->最遠的順序一次執行 ->若是沒有返回值,則執行下一個process_exception ->若是有返回值,直接交給離views最近的process_response處理(這個和process_request、process_view不一樣) ->有道 圖 ->階段四 理解process_template_response ->運用場景少 ->process_template_response方法的執行取決於視圖函數的返回的信息 ->視圖函數若是使用render方法返回信息,中間件裏的process_template_response方法就會被執行. ->概況有中間件的狀況下的整個生命週期 ->圖 ->緩存 ->保存的位置 ->本質 將渲染好的html本地保存一份,以後瀏覽器發來的請求就直接回復保存的內容 ->setting中配置 ->文件版本的配置 CACHES = { 'default': { 'BACKEND': 'django.core.cache.backends.filebased.FileBasedCache', 'LOCATION': os.path.join(BASE_DIR,'local_cache'), } } ->如何使用(3種類型) ->單獨視圖函數加裝飾器,整個界面作緩存 -> from django.views.decorators.cache import cache_page @cache_page(10) 單位是秒 ->查看文件夾中cache截圖 ->對頁面的某個部分作緩存 ->{%load cache%} ->{%cache 5000 k1%} 5000即秒,k1爲緩存的名稱 {%endcache%} ->有道圖片代碼 ->對全部頁面作緩存 ->中間件處理 ->添加中間件的位置及兩個中間件的原理(爲何要有兩個) ->一個取值 取response ->一個寫值 寫入response ->MIDDLEWARE = [ 'django.middleware.cache.UpdateCacheMiddleware', # 其餘中間件... 'django.middleware.cache.FetchFromCacheMiddleware', ] ->多種緩存存在的時候,哪一個生效 ->按照請求週期來分析,若是先return了 那麼不會到達後面的函數 ->信號 ->內置信號 ->至關於django內部給咱們預留了鉤子進行操做 ->內置信號的種類 Model signals pre_init # django的modal執行其構造方法前,自動觸發 post_init # django的modal執行其構造方法後,自動觸發 pre_save # django的modal對象保存前,自動觸發 post_save # django的modal對象保存後,自動觸發 pre_delete # django的modal對象刪除前,自動觸發 post_delete # django的modal對象刪除後,自動觸發 m2m_changed # django的modal中使用m2m字段操做第三張表(add,remove,clear)先後,自動觸發 class_prepared # 程序啓動時,檢測已註冊的app中modal類,對於每個類,自動觸發 Management signals pre_migrate # 執行migrate命令前,自動觸發 post_migrate # 執行migrate命令後,自動觸發 Request/response signals request_started # 請求到來前,自動觸發 request_finished # 請求結束後,自動觸發 got_request_exception # 請求異常後,自動觸發 Test signals setting_changed # 使用test測試修改配置文件時,自動觸發 template_rendered # 使用test測試渲染模板時,自動觸發 Database Wrappers connection_created # 建立數據庫鏈接時,自動觸發 ->內置信號的使用方法 ->導入 from django.core.signals import request_finished from django.core.signals import request_started from django.core.signals import got_request_exception from django.db.models.signals import class_prepared from django.db.models.signals import pre_init, post_init from django.db.models.signals import pre_save, post_save from django.db.models.signals import pre_delete, post_delete from django.db.models.signals import m2m_changed from django.db.models.signals import pre_migrate, post_migrate from django.test.signals import setting_changed from django.test.signals import template_rendered from django.db.backends.signals import connection_created ->註冊 ->__init__中使用 ->自定義信號 ->定義信號 ->註冊信號 ->觸發信號 ->有道圖片 ->form入門 ->form的概述及與model的關係 ->django提供的驗證模塊,一般和model一塊兒使用 ->form能夠離開model單獨對某個input框的內容作驗證 ->定義一個form from django.forms import fields,forms class MYForm(forms.Form): name=fields.CharField(max_length=32,min_length=8) pwd=fields.CharField() email=fields.EmailField(error_messages={'invalid':'格式錯誤'}) ->is_valid()數據驗證 ->數據傳入 x=MYFORM(request.POST) ->經過返回true ->失敗放回false ->errors ->obj.errors用來保存全部的錯誤信息 ->查看錯誤信息的幾種方式 ->obj.errors 顯示爲ul li格式 <ul class="errorlist"> <li> name<ul class="errorlist"><li>Ensure this value has at least 8 characters (it has 4).</li></ul> </li> <li> email<ul class="errorlist"><li>Enter a valid email address.</li></ul> </li> </ul> ->obj.errors.as_json() 能顯示錯誤代碼code { "name": [{ "message": "Ensure this value has at least 8 characters (it has 4).", "code": "min_length" }], "email":[{ "message": "Enter a valid email address.", "code": "invalid" }] } ->obj.errors.as_p() 此處不展開 ->obj.errors.as_table()此處不展開 ->定製錯誤信息爲中文 ->error_messages ->pwd=forms.CharField(max_length=16,min_length=6,error_messages={'min_length':'過短','max_length':'太長'}) ->error_messages內部字典的key就是as_json()時候的code ->errors中獲取某個字段的錯誤的方法 ->obj.errors['key'] --><ul class="errorlist"><li>Ensure this value has at least 8 characters (it has 4).</li></ul> ->obj.errors['key'][0] -->Ensure this value has at least 8 characters (it has 4). ->模板語言 obj.errors.key.0 ->cleaned_data ->驗證成功後,數據被保存在cleaned_data中 ->cleaned_data能夠直接被插入數據庫 ->models.xxx.obj.creat(**cleaned_data) ->實例:input框的姓名、密碼、email的提交 ->自動生成input框 ->輸出錯誤信息(僅文字) -> {{obj.user}}{{obj.user.errors.0}} {{obj.pwd}}{{obj.pwd.errors.0}} {{obj.email}}{{obj.email.errors.0}} ->保留原值 ->x=MYFORM(request.POST) ->form定製顯示格式 ->form自己只作驗證 ->form生成的html是插件作的 ->class CharField(Field): def __init__(self, *, max_length=None, min_length=None, strip=True, empty_value='', **kwargs): ->class Field: widget = TextInput # Default widget to use when rendering this type of Field. ->class TextInput(Input): input_type = 'text' template_name = 'django/forms/widgets/text.html' -><input type="{{ widget.type }}" name="{{ widget.name }}" {% if widget.value != None %} value="{{ widget.value }}" {% endif %} {% include "django/forms/widgets/attrs.html" %}> ->給字段設置插件 widget=widgets.* ->from django.forms import widgets email=fields.EmailField(error_messages={'invalid':'格式錯誤'},widget=widgets.Textarea(attrs={'class':'c1','xxx':'xxx2'})) ->設置樣式 attrs={'class':c1,'xxx':'xxx2'} ->再來個例子 pwd=fields.CharField(max_length=16,min_length=6,error_messages={'min_length':'過短','max_length':'太長'},widget=widgets.PasswordInput())#不寫括號也能夠 ->form的常見字段 ->Field required=True, 是否容許爲空 widget=None, HTML插件 label=None, 用於生成Label標籤或顯示內容 initial=None, 初始值 help_text='', 幫助信息(在標籤旁邊顯示) error_messages=None, 錯誤信息 {'required': '不能爲空', 'invalid': '格式錯誤'} show_hidden_initial=False, 是否在當前插件後面再加一個隱藏的且具備默認值的插件(可用於檢驗兩次輸入是否一直) validators=[], 自定義驗證規則 localize=False, 是否支持本地化 disabled=False, 是否能夠編輯 label_suffix=None Label內容後綴 CharField(Field) max_length=None, 最大長度 min_length=None, 最小長度 strip=True 是否移除用戶輸入空白 IntegerField(Field) max_value=None, 最大值 min_value=None, 最小值 FloatField(IntegerField) ... DecimalField(IntegerField) max_value=None, 最大值 min_value=None, 最小值 max_digits=None, 總長度 decimal_places=None, 小數位長度 BaseTemporalField(Field) input_formats=None 時間格式化 DateField(BaseTemporalField) 格式:2015-09-01 TimeField(BaseTemporalField) 格式:11:12 DateTimeField(BaseTemporalField)格式:2015-09-01 11:12 DurationField(Field) 時間間隔:%d %H:%M:%S.%f ... RegexField(CharField) regex, 自定製正則表達式 max_length=None, 最大長度 min_length=None, 最小長度 error_message=None, 忽略,錯誤信息使用 error_messages={'invalid': '...'} EmailField(CharField) ... FileField(Field) allow_empty_file=False 是否容許空文件 ImageField(FileField) ... 注:須要PIL模塊,pip3 install Pillow 以上兩個字典使用時,須要注意兩點: - form表單中 enctype="multipart/form-data" - view函數中 obj = MyForm(request.POST, request.FILES) URLField(Field) ... BooleanField(Field) ... NullBooleanField(BooleanField) ... ChoiceField(Field) ... choices=(), 選項,如:choices = ((0,'上海'),(1,'北京'),) required=True, 是否必填 widget=None, 插件,默認select插件 label=None, Label內容 initial=None, 初始值 help_text='', 幫助提示 ModelChoiceField(ChoiceField) ... django.forms.models.ModelChoiceField queryset, # 查詢數據庫中的數據 empty_label="---------", # 默認空顯示內容 to_field_name=None, # HTML中value的值對應的字段 limit_choices_to=None # ModelForm中對queryset二次篩選 ModelMultipleChoiceField(ModelChoiceField) ... django.forms.models.ModelMultipleChoiceField TypedChoiceField(ChoiceField) coerce = lambda val: val 對選中的值進行一次轉換 empty_value= '' 空值的默認值 MultipleChoiceField(ChoiceField) ... TypedMultipleChoiceField(MultipleChoiceField) coerce = lambda val: val 對選中的每個值進行一次轉換 empty_value= '' 空值的默認值 ComboField(Field) fields=() 使用多個驗證,以下:即驗證最大長度20,又驗證郵箱格式 fields.ComboField(fields=[fields.CharField(max_length=20), fields.EmailField(),]) MultiValueField(Field) PS: 抽象類,子類中能夠實現聚合多個字典去匹配一個值,要配合MultiWidget使用 SplitDateTimeField(MultiValueField) input_date_formats=None, 格式列表:['%Y--%m--%d', '%m%d/%Y', '%m/%d/%y'] input_time_formats=None 格式列表:['%H:%M:%S', '%H:%M:%S.%f', '%H:%M'] FilePathField(ChoiceField) 文件選項,目錄下文件顯示在頁面中 path, 文件夾路徑 match=None, 正則匹配 recursive=False, 遞歸下面的文件夾 allow_files=True, 容許文件 allow_folders=False, 容許文件夾 required=True, widget=None, label=None, initial=None, help_text='' GenericIPAddressField protocol='both', both,ipv4,ipv6支持的IP格式 unpack_ipv4=False 解析ipv4地址,若是是::ffff:192.0.2.1時候,可解析爲192.0.2.1, PS:protocol必須爲both才能啓用 SlugField(CharField) 數字,字母,下劃線,減號(連字符) ... UUIDField(CharField) uuid類型 ->常見字段的經常使用參數 required=True, 是否容許爲空 widget=None, HTML插件 label=None, 用於生成Label標籤或顯示內容 ->obj.user.label initial=None, 初始值 help_text='', 幫助信息(在標籤旁邊顯示) ->在後面的項目中有實例 error_messages=None, 錯誤信息 {'required': '不能爲空', 'invalid': '格式錯誤'} show_hidden_initial=False, 是否在當前插件後面再加一個隱藏的且具備默認值的插件(可用於檢驗兩次輸入是否一直) validators=[], 自定義驗證規則 ->自定義正則表達式 ->例子: ->username = fields.CharField(max_length=5, validators=[RegexValidator(r'^[0-9]+$', 'Enter a valid extension.', 'invalid')], ) -> 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 PublishForm(Form): # 使用自定義驗證規則 phone = fields.CharField(validators=[mobile_validate, ], error_messages={'required': '手機不能爲空'}, widget=widgets.TextInput(attrs={'class': "form-control", 'placeholder': u'手機號碼'})) disabled=False, 是否能夠編輯 ->對於各類字段的理解 ->咱們主要仍是使用CharField來進行定義 ->咱們能夠經過自定義正則的方式,來自行定義出不少django內部帶的或者是沒有帶的數據類型 ->FileField(Field)文件的處理 ->allow_empty_file=False 是否容許空文件 ->常規的文件處理 ->使用field.FileField()來處理文件 ->x=cleaned_data['Name'] x.name wb x.chunks() ->經常使用選項插件的處理 ->單選下拉框 ->使用choicesField ->choicesField(choices=[(1,上海),(2,廣州),(3,北京)],widget=widgets.Select) ->使用CharField ->user = fields.CharField(initial=2,widget=widgets.Select(choices=((1,'上海'),(2,'北京'),))) ->多選的下拉框 MultipleChoiceField(choices=((1,上海),(2,廣州),(3,北京))#列表/元組均可以 ->單選的radio處理 ->使用charField ->user = fields.CharField( initial=2, widget=widgets.RadioSelect(choices=((1,'上海'),(2,'北京'),)) ) ->使用ChoiceField ->user = fields.ChoiceField( choices=((1, '上海'), (2, '北京'),), initial=2, widget=widgets.RadioSelect ) ->單選的checkbox處理 user = fields.CharField(widget=widgets.CheckboxInput()) ->多選checkbox,值爲列表 user = fields.MultipleChoiceField( initial=[2, ], choices=((1, '上海'), (2, '北京'),), widget=widgets.CheckboxSelectMultiple ) ->實例: ->有道雲代碼 ->流程 ->類 ->字段 (校驗) ->插件 (生成html) ->form的初始化操做 initial
dic 界面生成的html則帶有內容