緩存穿透是用戶訪問一個不存在的key,導致請求穿透到資料庫。 問題關鍵是程式上要識別出這個key是一個錯誤key,不是由系統生成的key。每次添加或刪除緩存時維護一個key欄位查詢過濾器,例如:布隆過濾器、HashSet。這樣在訪問緩存前,可以對key先進行查詢過濾,判斷key是否存在,再往下執行業 ...
1.Django中的相應對象
構造函數格式:
HttpResponse(content=響應體,content_type=響應體數據類型,status=狀態碼)
作用:
向客戶端瀏覽器返回相應,同時攜帶響應體內容。
參數:
--content:表示返回的內容。
--status_code:返回的HTTP響應狀態碼(預設為200)。
--content_type:指定返回數據的MIME類型(預設為“text/html”)。瀏覽器會根據這個屬性,來顯示數據。如果是text/html,那麼就會解析這個字元串,如果是text/plain,那麼就會顯示一個純文本。
響應頭中常見的Content-Type:
-- text/html :預設的,html文件
--text/plain:純文本
--text/css:css文件
--text/javascript:js文件
--multipart/form-data:文件提交
--application/json:json傳輸
--application/xml:xml文件
2.GET處理
request.GET['參數名'] ##QueryDict
request.GET.get('參數名','預設值')
request.GET.getlist('參數名')
3.模板
(1)模板是可以根據字典數據動態變化的html網頁。
(2)模板可以根據視圖中傳遞的字典數據動態生成相應的HTML網頁。
(3)創建模板文件夾,一般位於<項目名>/templates
(4)在settings.py中,TEMPLATES的配置項:
"BACKEND":指定模板的引擎。
"DIRS":模板的搜索目錄(可以是一個或者多個)
"APP_DIRS":是否要在應用中的templates文件夾中搜索模板文件。
OPTIONS":有關模板的選項。
4.模板的載入
方案1
通過loader獲取模板,通過HttpResponse進行響應。註意是在視圖函數中實現。
例如
from django.template import loader #1 通過loader載入模板 t = loader.get_template("模板文件名") #2 將t轉換成HTML字元串 html = t.render(字典數據) #3 用響應對象將轉化的字元串內容返回給瀏覽器 return HttpResponse(html)
方案2,也是常用的方法
使用render(()直接載入並相應模板。註意是在視圖函數中實現。
from django.shortcuts import render, get_object_or_404 return render(request, "模板文件名", 字典數據)
5.視圖層與模板層之間的交互
(1).視圖函數中,可以將Python變數封裝到字典中,然後傳遞大模板。
例如
context = { "active_user": active_user, "group_list": group_list, "enable_backup_switch": config.get("enable_backup_switch"), } return render(request, "XXXX.html", context)
(2).模板中,我們可以用{{ 變數名 }}的語法,調用視圖傳進來的變數。
6.模板的變數
(1)能傳遞到模板中的數據類型
str --字元串 int ---整型
list --數組 tuple --元組
dict--字典 func--方法
obj --類實例化的對象
(2)在模板中使用變數語法
--{{ 變數名 }}
--{{ 變數名.index }} ---例如傳遞過來的變數是list
--{{ 變數名.key }} ---例如傳遞過來的變數是字典
--{{ 對象.方法 }}
--{{ 函數名 }}
7.模板過濾器
定義:在變數輸出時對變數的值進行處理
作用:可以通過使用 過濾器 來改變變數的輸出顯示
語法:
{{ 變數名 | 過濾器1:可選參數1 | 過濾器2:可選參數2 ... }}
8.模板的繼承
模板繼承可以使父模板的內容重用,子模版直接繼承父模板的全部內容並可以覆蓋父模板中相應的塊。
語法--父模板中:
(1)定義父模板中的塊block標簽;
(2)標識出哪些在子模塊中是允許被修改的;
(3)block標簽:在父模板中定義,可以在子模版中覆蓋,
語法--子模版中:
(1)繼承模板extends 標簽(寫在模板文件的第一行)
例如 {% extends "base.html" %}
(2)子模版 重寫父模板中的內容塊
{% block block_name %}
子模版塊用來覆蓋父模板塊中 block_name 塊的內容
{% endblock block_name %}
9.代碼中URL出現的位置
(1)模板【html】中的url
A.<a href='url'>超鏈接</a>
點擊後,頁面跳轉至url
B.<from action = 'url' method = 'post'>
from 表單中的數據,用post方法提交至url
(2)視圖函數中--302跳轉,HttpResponseRedirect('url')
將用戶地址欄中的地址跳轉到url。
10.url反向解析
url反向解析是指在視圖或模板中,用path定義的名稱來動態查找或者計算出相應的路由。
path函數的語法
path(route,views,name="別名")
例如:
path('page',views.page_vies,name="page_url")
根據path中的'name='關鍵字傳參給url確定了個唯一確定的名字,在模板
或視圖中,可以通過這個名字反向推斷出此url信息。
模板中使用,通過url標簽實現地址的方向解析:
{% url '別名'%}
{% url '別名' '參數值1' '參數值2' %}
在視圖函數中使用,可調用django中的reverse方法進行反向解析。
from django.urls import reverse
reverse('別名',args=[],kwargs={})
11.靜態文件配置
* 靜態文件配置位於settings.py中。
配置靜態文件的訪問路徑【配置預設存在】
# Static files (CSS, JavaScript, Images) STATIC_URL = "/static/" STATIC_ROOT = os.path.join(BASE_DIR, "static") STATICFILES_DIRS = [ os.path.join(BASE_DIR, "common/static"), ] STATICFILES_STORAGE = "common.storage.ForgivingManifestStaticFilesStorage"
說明:(1)指定訪問靜態文件時是需要通過/static/xxx或http://127.0.0.1:80/static/xxx.
[xxx表示具體的靜態資源位置];
(2)STATICFILES_DIRS ---保存的是靜態文件在伺服器端的存儲位置。
12.Django中的應用
應用在Django項目中是一個獨立的業務模塊,可以包含自己的路由、視圖、模板、模型。
(1)創建應用
step 1 用manage.py 中的子命令startapp 創建應用文件夾
python manage.py startapp XXXX
step 2 在settings.py 的INSTALLED_APPS = ()列表中配置安裝此應用。
13.分散式路由
Django中,主路由配置文件(urls.py)可以不處理用戶具體路由,主路由配置文件可以做請求的分發(分散式請求處理)。具體的請求可以由各自的應用來進行處理。
配置分散式路由
step 1 --主路由中調用include函數
導入的模塊
from django.urls import include, path
語法:include('app名字.url 模塊名')
作用:用於將當前路由轉到各個應用的路由配置文件的urlpatterns進行分散式處理。
例如 archery項目中的分散式配置。
urlpatterns = [ path("admin/", admin.site.urls), path("api/", include(("sql_api.urls", "sql_api"), namespace="sql_api")), path("", include(("sql.urls", "sql"), namespace="sql")), ]
14 應用下的模板
應用內部可以配置模板目錄
(1)應用下手動創建templates文件夾;
(2)settings.py中 開啟 應用模板功能,TEMPLATES 配置項中的"APP_DIRS": True 即可。
應用下templates 和外層templates都存在是,django的查找模板規則:
(1)優先查找外層templates目錄下的模板;
(2)按# Application definition 中 INSTALLED_APPS 配置下的 應用順序,逐層查找。
15 什麼是模型
模型是一個Python類,它是由django.db.models.Model派生出的子類。
一個模型類代表資料庫中的一張數據表。
模型類中每一個類屬性都代表資料庫中的一個欄位。
模型是數據交互的介面,是表示和操作資料庫的方法和方式。
16.ORM框架
定義: ORM(Object Relational Mapping)即對象關係映射,它是一種程式技術,它允許你使用類和對象對資料庫進行操作,從而避免通過SQL語句操作資料庫。
作用:
(1)建立模型類和表之間的對應關係,允許我們通過面向對象的方式來操作資料庫。
(2)根據設計的模型類生成資料庫中的表。
(3)通過簡單的配置就可以進行資料庫的部署或DB類型的切換。
有點:
(1)只需要面向對象編程,不需要面向資料庫編寫代碼。
對資料庫的操作都轉化成對類屬性和方法的操作;不用編寫各種資料庫的SQL語句。
(2)實現了資料庫模型與資料庫的解耦,屏蔽了不同資料庫操作上的差異。
不再關註於用的是MySQL、Oracle。。。等資料庫的內部細節;通過簡單的配置就可以輕鬆更換資料庫,而不需要修改代碼。
缺點:
對於複雜業務,使用成本較高;
根據對象的操作轉換成SQL語句,根據查詢的結果轉換成對象,在映射過程中有性能損失。
17.模型--資料庫遷移
遷移是Django同步您對資料庫所做的更改(添加欄位、刪除模型等)到您的資料庫模型的方式。
(1)生成遷移文件,執行 python manage.py makemigrations ,將應用下的models.py文件生成一個中間文件,並保存在migrations文件夾中。
(2)執行遷移腳本程式,--執行 python manage.py migrate ,執行遷移程式實現遷移。將每個應用下的makemigrations目錄中的中間文件同步回資料庫。
18. 模型---欄位類型
常見欄位類型相關說明補充如下:
欄位類型 | 編程語言 | 資料庫語言 | 備註 |
BooleanField() | 使用True或False來表示值。 |
tinyint(1) |
在資料庫中,使用1或0來表示具體的值。 |
NullBooleanField() |
可以為空的布爾值。 | ||
CharField(Field) | varchar() | 必須提供max_length參數, max_length表示字元長度 | |
DateField() | 表示日期 | date |
參數: auto_now:每次保存對象時,自動設置該欄位為當前時間(取值:True/False); auto_now_add:當對象第一次被創建時自動設置當前時間(取值:True/False); default:設置當前時間(取值:字元串格式時間,如:'2019-10-15'); 以上三個參數只能多選一。 |
DateTimeField() | 表示日期和時間 | datetime(6) |
參數同DateField. |
DecimalField() | 使用小數表示該列的值 |
使用小數 decimal(x,y) |
參數: max_digits,小數總長度【位數總數】,包括小數點後的位數,該值必須大於等於decimal_places; decimal_places,小數位長度【小數點後的數字數量】。 |
FloatField() | 浮點型 | double | 編程語言中和資料庫中都使用小數表示值。 |
EmailField() | 字元串類型 | varchar |
Django Admin以及ModelForm中提供驗證機制。 編程語言和資料庫中使用字元串。 |
IPAddressField() | 字元串類型 | Django Admin以及ModelForm中提供驗證 IPV4 機制 | |
GenericIPAddressField() |
字元串類型 |
Django Admin以及ModelForm中提供驗證 Ipv4和Ipv6。 參數:
|
|
IntegerField() | 整數列 | int |
編程語言和資料庫中使用整數。 |
SmallIntegerField() | 小整數 - 32768 ~ 32767 |
||
BigIntegerField() | 長整型(有符號的) - 9223372036854775808 ~ 9223372036854775807 |
||
ImageField() | 字元串 | varchar(100) |
在資料庫中為了保存圖片的路徑【路徑保存在資料庫中,文件上傳到指定目錄】。 編程語言和資料庫中使用字元串。 參數:
|
TextField() | 文本類型 | longtext |
表示不定長的字元數據。 |
19. 模型 --欄位選項
欄位選項時指創建列時指定的額外的信息。允許出現多個欄位選項,多個選項之間用【,】隔開。
欄位選項 | 作用描述 |
primary_key |
如果設置為True,表示該列為主鍵,如果指定一個欄位為主鍵,則此表不會再自動創建id欄位。 |
blank |
Admin中是否允許用戶輸入為空 表單提交時可以為空。 設置為True時,欄位可以為空;設置為False時,欄位則必須填寫。 |
null |
如果設置為True,表示該列值允許為空。預設為False,如果此選項為False,建議加入default選項來設置預設值。 |
default |
資料庫中欄位的預設值。 設置所在列預設值,如果欄位選項null=False,建議添加此項。 |
db_index | 資料庫中欄位是否可以建立索引(db_index = True )。如果為True,表示為該列增加索引。 |
unique |
|
db_column | 欄位的列名。指定列的名稱,如果不指定的話則採用屬性名稱作為列名。 |
verbose_name | Admin中顯示的欄位名稱。設置此欄位在admin界面上的顯示名稱。 |
choices | Admin中顯示選擇框的內容,用不變動的數據放在記憶體中從而避免跨表操作。 |
error_messages | 自定義錯誤信息(字典類型),從而定製想要顯示的錯誤信息。 |
validators | 自定義錯誤驗證(列表類型),從而定製想要的驗證規則。 |
20 模型--Meta類
使用內部Meta類來給模型賦予屬性,Meta類下有很多內建的類屬性,可以對模型類做一些控制。
部分屬性說明如下:
屬性 | 屬性說明 |
managed | 因為Django會自己主動依據模型類生成映射的資料庫表。假設你不希望Django這麼做。能夠把managed的值設置為False。 |
db_table |
db_table是用於指定自己定義資料庫表名的。Django有一套預設的依照一定規則生成數據模型相應的資料庫表名。假設你想使用自己定義的表名,就通過這個屬性指定。 |
verbose_name | 給模型類起一個更可讀的名字。 |
verbose_name_plural | 這個選項是指定。模型的複數形式是什麼。 |
db_tablespace |
有些資料庫有資料庫表空間,比方Oracle。通過db_tablespace來指定這個模型相應的資料庫表放在哪個資料庫表空間。 |
unique_together | unique_together這個選項用於:當你須要通過兩個欄位保持唯一性時使用。 |
abstract |
這個屬性是定義當前的模型類是不是一個抽象類。所謂抽象類是不會相應資料庫表的。一般我們用它來歸納一些公共屬性欄位,然後繼承它的子類能夠繼承這些欄位。 |
permissions |
permissions主要是為了在Django Admin管理模塊下使用的。設置這個屬性能夠讓指定的方法許可權描寫敘述更清晰可讀。 |
ordering | 這個欄位是告訴Django模型對象返回的記錄結果集是依照哪個欄位排序的。 |
在此,補充一個model的知識點,與Meta無關,就是__str__(self)方法。可以在模型類中定義__str__方法,自定義QuerySet中的輸出格式。這樣可視化程度更高,方便調試。
21.ORM--操作
基本操作包括增刪改查操作,即CRUD操作。
CRUD是指在做計算處理時的增加(Create)、讀取查詢(Read)、更新(Update)和刪除(Delete)。
ORM CRUD 核心--> 模型類.管理器對象。
每個繼承自models.Model的模型類,都會有一個objects對象被同樣繼承下來。這個 對象叫管理器對象。
資料庫的增刪改查可以通過模型的管理器實現。
class MyModel(models.Model): .... MyModel.objects.create(...) ##objects 是管理器對象
創建數據
Django ORM 使用一種直觀的方式把資料庫表中的數據表示成Python對象。
創建數據中每一條記錄就是創建一個數據對象。
方案1
MyModel.objects.create(屬性1=值1,屬性2=值2)
成功:返回創建好的實體對象;失敗:拋出異常。
方案2
創建MyModel實例對象,並調用save()進行保存。
obj = MyModel(屬性=值,屬性=值)
obj.屬性=值
obj.save()
22.查詢簡介
資料庫的查詢需要使用管理器對象進行,通過MyModel.objects管理方法調用查詢方法。
查詢方法 | 用法 | 作用 | 等同於SQL | 返回值 | 簡單舉例 |
all() | MyModel.objects.all() | 查詢MyModel實體中所有所有的數據。 | select*from table | QuerySet 容器對象[類似數組],內部存放MyModel實例 |
books =Book.objects.all() for book in books: print("書名",book.title,'出版社:' book.pub) |
values(’列1‘,’列2‘) | MyModel.objests.values(...) | 查詢部分列的數據並返回 | select列1,列2 from table |
QuerySet.返回查詢結果容器,容器記憶體字典,每個字典代表一條數據。格式為:{’列1‘:值1,’列2‘:值2} |
a2=Book.objects.values('title','pub') for book in a2 print(book[title]) |
values_list('列1','列2'...) | MyModel.objects.values_list(...) | 返回元組形式的查詢結果 | select 列1,列2 from table | QuerySet 容器對象,內部存放’元組‘。會將查詢出來的數據封裝到元組中,再封裝到查詢集合QuerySet中。 |
a3 = Book.objects.values_list('title','pub') for book in a3: print(book[0]) |
order_by() | MyModel.objects.order_by('-列','列') | 與all()方法不同,它會用sql語句的order by 子句對查詢結果進行根據指定欄位選擇性的進行排序。 |
預設是按照升序排序,降序排序則需要在列前增加’-‘表示。 可以和其它查詢方法組合使用。 |
||
filter(條件) | MyModel.objects.filter(屬性1=值1,屬性2=值2) | 返回符合此條件的全部的數據集 | QuerySet容器對象,內部存放MyModel實例 |
當多個屬性在一起時為”與“關係。 books = Book.objects.filter(pub="清華大學出版社") for book in books: print("書名",book.title) |
|
exclude(條件) | MyMOdel.objects.exclude(條件) | 返回不包含(不符合)此條件的全部的數據集 |
books = models.Book.objects.exclude(pub=”清華大學出版社“,price=50) for book in books: print(book) |
||
get(條件) | MyModel.objects.get(條件) | 返回滿足條件的唯一一條數據 |
該方法只能返回一條數據。查詢結果多餘一條數據則拋出異常--Model.MultipleObjectsReturned異常。查詢結果如果沒有數據則拋出Model.DoesNotExist異常。 |
23.查詢謂詞
定義:做更靈活的條件查詢時需要使用查詢謂詞。
說明:每一個查詢謂詞是一個獨立的查詢功能。
查詢謂詞 | 功能 | 舉例 |
__exact | 等值匹配 |
Book.objects.filter(id__exact=1) ##等同於select * from books where id =1 |
__contains |
包含指定值. __startswith:以XXX開始; __endswith:以XXX結束。 |
Author.objects.filter(name__contains='w') ##等同於 select * from author where name like '%w%' |
__gt |
大於指定值; __gte:大於等於; __lt:小於 __lte:小於等於 |
Author.objects.filter(age__gt=50) ##等同於 select * from author where age>50 |
__in | 查找數據是否在指定範圍內 |
Author.objects.fileter(country__in=['中國','南韓','越南']) ##等同於select * from author where country in ('中國','南韓',越南'') |
__range | 查找數據是否在指定的時間範圍內 |
Author.objects.filter(age__range=(35,50)) ##等同於 select * from author where age between 35 and 50 |
24 ORM 更新操作
更新單個數據
修改單個實體的某些欄位的步驟:
step 1. 查
通過get()等到要修改的實體對象;
step 2 改
通過 對象.屬性 的方式 修改數據
step 3 保存
通過對象.save()保存數據
批量更新數據
直接調用QuerySet的update(屬性=值)實現批量修改。
例如
##將id大於3的所有圖書價格定為0元 books =Book.objects.filter(id__gt=3) books.update(price=0) ##返回成功執行影響的行數
25.ORM--刪除操作
單個數據刪除
步驟
step 1 查找
查詢對應的數據對象
step 2 刪除
調用這個數據對象的delete()方法進行刪除。
try: auth=Author.objects.get(id=1) auth.delete() except: print(刪除失敗)
批量刪除
step 1 查找
查詢結果集中滿足條件的全部QuerySet查詢集合對象
step 2 調用查詢集合對象的delete()方法實現刪除
##刪除全部作者中,年齡大於65的全部信息 auths = Author.objects.filter(age__gt=65) auths.delete()
26 F對象
定義:一個F對象代表資料庫中某條記錄的欄位的信息。
作用:通常是對資料庫中的欄位值在不獲取的情況下進行操作,用於類屬性(欄位)之間的比較。
語法:
from django.db.models import F F('列名')
示例:
更新Book實例中所有的零售價漲10元。
如果不用F對象,如下:
books = Book.objects.all() for book in books: book.market_price=book.marget_price+10 book.save()
使用F對象,可以簡化如下:
Book.objects.all().update(market_price=F('market_price')+10)
實例2
對資料庫中兩個欄位的值進行比較,例如,列出那些書的零售價高於定價?
books = Book.objects.filter(market_price__gt=F('price')) for book in books: print(book.title,'定價:',book.price,'現價:',book.market_price)
27.Q對象
當在獲取查詢結果集,使用複雜的邏輯或|、邏輯非~等操作時,可以藉助於Q對象進行操作。
如,想找出定價低於20元或中國機械出版社的全部書,可以寫成:
Book.objects.filter(Q(price__lt=20)|Q(pub="中國機械出版社"))
Q對象在數據包 django.db.models中,需要先導入再使用。
運算符:
& 與操作
| 或操作
~ 非操作
from django.db.models import Q Q(條件1)|Q(條件2) ##表示需要 條件1成立或者條件2成立; Q(條件1)&Q(條件2) ##條件1和條件2同時成立; Q(條件1)&~Q(條件2) ##條件1成立且條件2不成立。
28.聚合查詢
整表聚合
不帶分組的聚合查詢是指將全部的數據進行集中統計查詢。
聚合函數需要從django.db.models導入,常用的聚合函數:Sum、Avg、Count、Max、Min ---【註意:首字母大寫】。
語法:
MyModel.objects.aggregate(自定義的結果變數名=聚合函數('列'))
返回結果:結果變數名和值組成的字典,格式為:{"結果變數名":值}
分組聚合
分組聚合是指通過計算查詢結果中每一個對象所關聯的對象集合,從而得出總計值值(當然也可以是平均值或總和),即為查詢集的每一項生成集合。
語法:
QuerySet.annotate(自定義結果變數名=聚合函數('列'))
返回值:QuerySet。
簡單來講就是先通過MyModel.objects.values()進行查詢,然後通過.annotate分組。
29.原生資料庫操作
Django也支持之間用sql語句對資料庫進行查詢操作。
查詢:使用MyModel.objects.raw()進行資料庫查詢操作。
語法:
MyModel.objects.raw(sql語句,拼接參數)
返回值:RawQuerySet集合對象【只支持基礎操作,比如迴圈】
示例:
books = models.Book.objects.raw('select * from bookstore_book') for book in books: print(book)
使用原生語句時小心SQL註入。即 用戶通過數據上傳,將惡意的SQL語句提交給伺服器,從而達到攻擊效果。
30.原生資料庫操作--cursor
可以支持查詢、更新、刪除。
step 1 導入cursor所在的包
from django.db import connection
step 2 用創建cursor類的構造函數創建cursor對象,再使用cursor對象,為保證在出現異常時能釋放cursor資源,通常使用with語句進行創建操作。
from django.db import connection with connection.cursor() as cur: cur.execute('執行SQL語句','拼接參數')
31. admin管理後臺
註冊自定義模型類
若要自己定義的模型類也能在/admin後臺管理界面中顯示和管理,需要將自己的類註冊到後臺管理界面。
註冊步驟:
step 1.在應用app中的admin.py中導入註冊要管理的模型models類,如:
from .models import Book
step 2.調用admin.site.register方法進行註冊,如
admin.site.register(自定義模型類)
模型管理器類
作用:為後臺管理界面添加便於操作的新功能。
說明:管理後臺類須繼承自django.contrib.admin里的ModelAdmin類。
使用方法
step 1.在<應用app>/admin.py里定義模型管理類
class xxxxManager(admin.ModelAdmin):
......
step 2 綁定註冊模型管理器和模型類
from django.contrib import admin from .models import * admin.site.register(YYYY,xxxxmanager) ###綁定YYYY模型類與管理器類xxxxManager
類xxxxManager 幾個常用的屬性
list_display = [] ##列表頁顯示那些欄位的列;即去控制那些欄位會顯示在Admind顯示列表中。
list_dispaly_links =[] ##控制list_display中的欄位,那些可以鏈接到修改頁;
list_filter=[] ##添加過濾器;即設置激活Admin修改列表頁面右側欄中的過濾器。
search_fields = [] ##添加搜索框;
list_editable = [] ##添加可在列表頁編輯的欄位,允許在更改列表頁面上直接進行欄位編輯。