目錄css
res = models.Book.objects.all().values('title') print(res) # <QuerySet [{'title': '三國演義'}, {'title': '紅樓夢'}, {'title': '水滸傳'}, {'title': '天龍八部'}]> for i in res: print(i,type(i)) # <class 'dict'> print(i.title) # AttributeError: 'dict' object has no attribute 'title' ,for循環出來就是第一個普通的字典,字典沒有點取值的方式
only:查詢only後括號內指定的字段,查詢一次,以後再點字段不會再查數據庫了;若是點的是其餘字段,會再次操做數據庫;html
# 點指定字段 res = models.Book.objects.only('title') print(res) # 返回的是一個QuerySet對象,列表內是一個個類的對象; for i in res: print(i.title)
# 點其餘字段 res = models.Book.objects.only('title') # print(res) for i in res: print(i.price)
refer:refer和only互爲反關係,按照refer指定字段查找,操做數據庫一次,以後對象點指定的屬
性,每點一次,操做一次數據庫;若是點其餘字段,總體只操做一次數據庫。前端
# 點指定字段 res = models.Book.objects.defer('title') # print(res) for i in res: print(i.title)
# 點其餘字段 res = models.Book.objects.defer('title') # print(res) for i in res: print(i.price)
select_related:括號內只能放外鍵字段,而且外鍵字段的類型只能是一對多,或者 一對一,不能是多對多;
內部是自動連表操做,會將括號內外鍵字段所關聯的表與當前表自動拼接成一張表,而後將表中的數據一個個查詢出
來封裝成一個個的對象。這樣作的好處就在於跨表也不須要重複的走數據庫了,減輕數據庫的壓力。
select_related括號內能夠放多個外鍵字段,逗號隔開,會將多個外鍵字段關聯的表與當前表所有拼成一張大表。python
res = models.Book.objects.select_related('publish') print(res) # <QuerySet [<Book: Book object>, <Book: Book object>, <Book: Book object>, <Book: Book object>]> for i in res: print(i.publish) # 只操做一次數據庫 ''' Publish object Publish object Publish object Publish object '''
一對多的狀況:jquery
res = models.Book.objects.select_related('publish') # print(res) for i in res: print(i.publish) # 只操做一次數據庫
一對一的狀況:ajax
res = models.Author.objects.select_related('author_detail') # print(res) for i in res: print(i.author_detail) # 內部作的也是聯表操做,同一對多同樣,也是內鏈接
多對多的狀況:sql
res = models.Book.objects.select_related('author') # print(res) for i in res: print(i.author) ''' 報錯信息: django.core.exceptions.FieldError: Invalid field name(s) given in select_related: 'author'. Choices are: publish '''
prefetch_related:內部是子查詢,會自動幫你按步驟查詢多張表 而後將查詢的結果封裝到對象中,
給用戶的感受好像仍是連表操做,括號內支持傳多個外鍵字段 而且沒有類型限制。
特色:每放一個外鍵字段 就會多走一條sql語句 多查詢一張表數據庫
res = models.Book.objects.prefetch_related('publish','authors') # print(res) for i in res: print(i.publish,i.authors.all()) ''' Publish object <QuerySet [<Author: Author object>, <Author: Author object>]> Publish object <QuerySet []> Publish object <QuerySet []> Publish object <QuerySet []> '''
二者之間的優缺點比較django
結合實際狀況,看錶的數據量的大小, 兩張表都特別大的狀況下,連表操做可能耗時更多;
choices字段類型,在獲取值得時候統一的句式:get_字段名_display()編程
1.建表
# models.py文件 from django.db import models # Create your models here. class User(models.Model): username = models.CharField(max_length=32) password = models.BigIntegerField() gender_choices = ( (1,'男'), # 第一個參數能夠是數字,也能夠是自定義的字符串 (2,'女'), (3,'其餘'), ) gender = models.IntegerField(choices = gender_choices)
2.數據庫遷移命令 數據錄入
這裏咱們使用的是django自帶的測試用的db.sqlite3數據庫,並在表中添加數據
菜單欄Tools>Run manage.py Task
django 終端:1.makemigrations 2.migrate
3.測試環境配置及示例分析
from django.test import TestCase # Create your tests here. import os if __name__ == "__main__": os.environ.setdefault("DJANGO_SETTINGS_MODULE", "day56.settings") import django django.setup() from app01 import models user_obj1 = models.User.objects.get(pk = 1) user_obj2 = models.User.objects.get(pk = 4) # print(user_obj1.gender) # 1 # print(user_obj2.gender) # 4 這裏id=4並無gender對應的性別關係,但不報錯。 print(user_obj1.get_gender_display()) # 男 正確的獲取方式 print(user_obj2.get_gender_display()) # 4 沒有性別的對應關係獲取到的仍是數字自己
MTV模型:
django就是MTV框架,但本質仍是MVC
MTV:
M:models
T:templates
V:views
MVC:
M:models
V:views
C:controller 路由匹配
MVVM :前端框架,好比:Vue
AJAX(Asynchronous Javascript And XML)翻譯成中文就是「異步的Javascript和XML」。
即便用Javascript語言與服務器進行異步交互,傳輸的數據爲XML(固然,傳輸的數據不僅是XML)。
AJAX 不是新的編程語言,而是一種使用現有標準的新方法。
AJAX 最大的優勢是在不從新加載整個頁面的狀況下,能夠與服務器交換數據並更新部分網
頁內容。(這一特色給用戶的感覺是在不知不覺中完成請求和響應過程)
AJAX 不須要任何瀏覽器插件,但須要用戶容許JavaScript在瀏覽器上執行。
瞭解:
XML也是一門標記語言 該語法應用場景 1.寫配置文件 2.能夠寫前端頁面(odoo框架中 erp) 每家公司都會有屬於這家公司獨有的內部管理軟件 專門用來開發企業內部管理軟件 框架 odoo odoo框架內部功能實現所有依賴於python2
1)搜索引擎根據用戶輸入的關鍵字,自動提示檢索關鍵字。
2)還有一個很重要的應用場景就是註冊時候的用戶名的查重。
其實這裏就使用了AJAX技術!當文件框發生了輸入變化時,使用AJAX技術向服務器發送一個請求,而後服
務器會把查詢到的結果響應給瀏覽器,最後再把後端返回的結果展現出來。
當輸入用戶名後,把光標移動到其餘表單項上時,瀏覽器會使用AJAX技術向服務器發出請求,服務器會
查詢名爲lemontree7777777的用戶是否存在,最終服務器返回true表示名爲lemontree7777777的用戶
已經存在了,瀏覽器在獲得結果後顯示「用戶名已被註冊!」。
優勢:
- AJAX請求無須刷新整個頁面;
- 兩個關鍵點:1.局部刷新,2.異步請求
- AJAX使用JavaScript技術向服務器發送異步請求;
- 由於服務器響應內容再也不是整個頁面,而是頁面中的部份內容,因此AJAX性能高;
$.ajax({ })
// ajax基本語法結構 $.ajax({ url:'', // 數據提交的後端地址 不寫就是往當前頁面提交 也能夠寫後綴 也能夠寫全稱 跟actions同樣 type:'post', // 提交方式 默認是get請求 data:{'i1':$('#d1').val(),'i2':$('#d2').val()}, // 提交的數據 success:function (data) { // 形參data,就是異步提交以後後端返回的結果,兩個data不是同一個 $('#d3').val(data) // 回調機制須要作的事情 } }) // 注意:使用ajax django三板斧都再也不做用與頁面 而是與data交互
# urls.py文件 # Ajax在post發送post請求的時候記得註銷掉settings.py文件中的中間件 from app01 import views urlpatterns = [ url(r'^admin/', admin.site.urls), url(r'^about_ajax/',views.xxx), ]
# views文件 from django.shortcuts import render,HttpResponse # Create your views here. def xxx(request): # print(request.is_ajax()) # 判斷當前請求是不是Ajax請求,返回布爾值 # print(request.POST) # ajax發送的post請求,普通的鍵值對也在request.POST中獲取 # if request.method == 'POST': if request.is_ajax(): # True i1 = request.POST.get('i1') # 默認取列表的最後一個元素, i2 = request.POST.get('i2') # print(i1,type(i1)) # 字符串類型 1 <class 'str'> res = int(i1) + int(i2) return HttpResponse(res) # 把結果給異步回調函數success return render(request, 'xxx.html')
// 這裏直接使用JQuery封裝好的方法,就再也不用原生的js版本了。 // xxx.html 文件 <!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>Title</title> <script src="https://cdn.bootcss.com/jquery/3.4.1/jquery.min.js"></script> </head> <body> <input type="text" id="d1"> + <input type="text" id="d2"> = <input type="text" id = "d3"> <button id="d4" style="color:orange">點我發送請求</button> <script> $('#d4').on('click',function () { $.ajax({ url:'', type:'post', data:{'i1':$('#d1').val(),'i2':$('#d2').val()}, // 提交數據 data對應的是個字典,裏面是鍵值對 success:function (data) { // 形參data就是異步提交以後後端返回的結果 {#alert(data)#} $('#d3').val(data) // 後端返回的結果就是這裏的data接收的 } }) }) </script> </body> </html>
先後端交互是一個數據編碼格式,針對不一樣的數據,後端會進行不一樣的處理。 通常請求: request.POST 文件格式的請求: request.FILES
發送請求三種編碼格式:
1.urlencoded
2.formdata # form表單日後端發文件指定的編碼格式
3.application/json # Ajax日後端發送文件指定的編碼格式
能朝後端發數據的請求有哪些
a標籤href參數 get請求 form表單 get/post ajax get/post get請求的數據格式比較單一,這裏不作研究。 url?xxx=ooo&yyy=zzz
第一種編碼格式:urlencoded
1).默認是urlencoded編碼 Content-Type: application/x-www-form-urlencoded urlencoded所對應的數據格式: username=jason&password=123 django後端針對urlencoded編碼格式的數據 會自動解析而且幫你封裝到request.POST中
第二種編碼格式:multipart/form-data
2). form表單指定enctype="multipart/form-data", Content-Type: multipart/form-data; boundary=----WebKitFormBoundaryhjKCHQHDmcE62iMQ 針對formdata格式的數據 你在瀏覽器上是沒法查看到 若是是一個文件對象,django後端也會自動識別,放到request.FILES中
當form表單不指定參數enctype="multipart/form-data"時發生的狀況:
代碼示例:
from django.shortcuts import render,HttpResponse def about_form(request): if request.method=='POST': print(request.POST) # <QueryDict: {'username': ['zhang'], 'password': ['123']}> print(request.FILES) # <MultiValueDict: {'myfile': [<InMemoryUploadedFile: ORM查詢優化.md (application/octet-stream)>]}> return render(request,'about_form.html') ''' 當about_form.html文件中form標籤參數不指定enctype="multipart/form-data"時,後端打印結果爲: <QueryDict: {'username': ['zhang'], 'password': ['123'], 'myfile': ['ORM查詢優化.md']}> <MultiValueDict: {}> 沒法拿到文件對象 '''
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>Title</title> <script src="https://cdn.bootcss.com/jquery/3.4.1/jquery.min.js"></script> <link rel="stylesheet" href="https://cdn.bootcss.com/twitter-bootstrap/3.4.1/css/bootstrap.min.css"> <script src="https://cdn.bootcss.com/twitter-bootstrap/3.4.1/js/bootstrap.min.js"></script> </head> <body> <form action="" method="post" enctype="multipart/form-data"> username:<input type="text" name="username"> password:<input type="text" name="password"> <input type="file" name="myfile"> <input type="submit"> </form> </body> </html>
3).form表單沒法發送json格式的數據,只能藉助於ajax
ajax發送
1.urlencoded
2.application/json post請求下前端發送json格式數據
3.formdata
第一種編碼格式:默認的urlencoded編碼格式
1).Content-Type: application/x-www-form-urlencoded; charset=UTF-8 ajax默認的編碼格式也是urlencoded,也就意味着後端django也是將數據解析到request.POST中
在涉及到先後端交互的時候 必定要作到數據的格式與編碼格式一致
第二種編碼格式:html文件中添加contentType參數爲application/json,日後端發json格式數據
2).django後端針對application/json編碼格式的數據,不會作任何處理,數據怎麼來的,只會原封不動的放到request.body中
前端js | 後端json |
---|---|
stringify | dumps |
parse | loads |
第三種編碼格式:multipart/form-data
數據傳到後端直接分紅兩個部分,數據信息放在POST中,文件放在FILES中
代碼示例:
# views.py 文件 from django.shortcuts import render,HttpResponse def about_form(request): if request.method=='POST': print(request.body) # b'{"username":"zhang","passowrd":"123"}' json_bytes = request.body import json # 方式1: # user_dic = json.loads(json_bytes.decode('utf8')) # print(user_dic) # {'username': 'zhang', 'passowrd': '123'} # 方式2: user_dic = json.loads(json_bytes) # 自動幫你解碼家反序列化 print(user_dic,type(user_dic)) # {'username': 'zhang', 'passowrd': '123'} <class 'dict'> return render(request,'about_form.html')
<!--about_form.html文件--> <!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>Title</title> <script src="https://cdn.bootcss.com/jquery/3.4.1/jquery.min.js"></script> </head> <body> <button id="d1">點我發送json格式數據</button> <script> $('#d1').click(function () { $.ajax({ url:'', type:'post', contentType:'application/json', // 不寫默認編碼格式爲urlencoded,form表單enctype指定編碼格式 data:JSON.stringify({'username':'zhang','passowrd':'123'}), success:function (data) { alert(123) } }) }) </script> </body> </html>
藉助於內置對象new,該對象便可以攜帶文件數據,一樣也支持普通的鍵值對
代碼示例:
from django.shortcuts import render,HttpResponse def about_form(request): if request.method=='POST': # 數據傳到後端直接分紅兩個部分,分別放在POST中,和FILES中 print(request.POST) # <QueryDict: {'username': ['zhang'], 'password': ['123']}> print(request.FILES) # <MultiValueDict: {'myfile': [<InMemoryUploadedFile: ORM查詢優化.md (application/octet-stream)>]}> return render(request,'about_form.html')
<!--about_form.html文件--> <!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>Title</title> <script src="https://cdn.bootcss.com/jquery/3.4.1/jquery.min.js"></script> </head> <body> username:<input type="text"> password:<input type="password"> myfile:<input type="file" id="d1" name="myfile"> <button id="d2">點我發送文件</button> <script> $('#d2').click(function () { // 先生成一個內置對象 var MyFormData = new FormData(); // 1. 先添加普通的鍵值 MyFormData.append('username','zhang'); // 添加了一組普通的鍵值對 MyFormData.append('password','123'); // 2. 添加文件數據 MyFormData.append('myfile',$('#d1')[0].files[0]); // 如何獲取input框中文件對象$('#d1')[0].files[0] $.ajax({ url:'', type:'post', data:MyFormData, // 發送文件必需要指定的兩個參數 contentType:false, // 不使用任何編碼 MyFormData對象內部自帶編碼 django後端可以識別 processData:false, // 不要處理數據 success:function (data) { } })
序列化目的:將數據整合成一個大字典形式,方便先後端數據的交互,實現方便先後端分離。
代碼示例:
from app01 import models from django.core import serializers def back_dict_in_list(request): user_queryset = models.User.objects.all() # [{username:...,password:...,hobby:...,},{},{},{}] # user_list = [] # for data in user_queryset: # 數據量比較大的狀況下書寫麻煩 # user_list.append( # {'username':data.username, # 'password':data.password, # 'gender':data.get_gender_display(), # # } # ) user_list = serializers.serialize('json', user_queryset) # 能指定序列化到前端的數據格式 return HttpResponse(user_list)