1,django原生FBV
urls.py
# 1,django原生FBV
path('origin/',FBV.view),
path('origin2/<str:id>/',FBV.view_detail)
view.py
import json
from django.db.models import Q
from django.views.decorators.csrf import csrf_exempt,csrf_protect
from mysystem.models import Student
from django.http import JsonResponse
# 關閉驗證
# @csrf_exempt
def view(request):
if request.method == 'GET':
"""獲取多個學生資訊"""
# 1. 讀取資料庫
students_list = list(Student.objects.values())
# 2. 返回資料
return JsonResponse(data=students_list, status=200, safe=False)
elif request.method == 'POST':
"""新增一個學生資訊"""
# 1. 接收客戶單提交的資料,驗證客戶端的資料
data = json.loads(request.body)
name = data.get("name")
sex = data.get("sex")
age = data.get("age")
classmate = data.get("classmate")
description = data.get("description")
# 2. 運算元據庫,儲存資料
instance = Student.objects.create(
name=name,
sex=sex,
age=age,
classmate=classmate,
description=description,
)
# 3. 返回結果
return JsonResponse(data={
"id": instance.pk,
"name": instance.name,
"sex": instance.sex,
"age": instance.age,
"classmate": instance.classmate,
"description": instance.description,
}, status=201)
# 開啟驗證
# @csrf_protect
def view_detail(request, id):
if request.method == 'DELETE':
"""刪除一個學生資訊"""
try:
Student.objects.filter(pk=id).delete()
except:
pass
return JsonResponse(data={}, status=204)
elif request.method == 'PUT':
"""更新一個學生資訊"""
# 1. 接收客戶單提交的資料,驗證客戶端的資料
data = json.loads(request.body)
name = data.get("name") # alt+j 選中多個一樣的
sex = data.get("sex")
age = data.get("age")
classmate = data.get("classmate")
description = data.get("description")
# 2. 運算元據庫,儲存資料
try:
instance = Student.objects.get(pk=id)
instance.name = name
instance.sex = sex
instance.age = age
instance.classmate = classmate
instance.description = description
instance.save()
except Student.DoesNotExist:
return JsonResponse(data={}, status=404) # 沒有內容
# 3. 返回結果
return JsonResponse(data={
"id": instance.id,
"name": instance.name,
"sex": instance.sex,
"age": instance.age,
"classmate": instance.classmate,
"description": instance.description,
}, status=201)
elif request.method == 'GET':
"""獲取一條資料"""
try:
print(id)
instance = Student.objects.filter(
Q(name__icontains=id) | Q(description__icontains=id)
)
results = [
{
'name': item.name,
'description': item.description
}
for item in instance
]
return JsonResponse({'res': results},status=200)
# return JsonResponse(data={
# "id": instance.id,
# "name": instance.name,
# "sex": instance.sex,
# "age": instance.age,
# "classmate": instance.classmate,
# "description": instance.description,
# }, status=200)
except Student.DoesNotExist:
return JsonResponse(data=None, status=404) # 沒有內容
幾個問題:
1,Django的csrf驗證怎麼關閉取消?
作用:
Django框架中的CSRF(跨站請求偽造)保護是一種安全措施,它的作用是防止攻擊者透過偽造請求在使用者已經登入的Web應用中執行惡意操作。具體來說,CSRF保護確保了以下幾點:
保護使用者狀態:在使用者透過Web應用與伺服器互動時,CSRF保護防止了使用者在不知情的情況下,由第三方網站操作使用者的Web應用會話。
同源策略:預設情況下,Web瀏覽器遵循同源策略(SOP),它限制了一個源(域名、協議和埠)的文件或指令碼與另一個源的資源進行互動。CSRF利用了這一策略,因為瀏覽器允許跨域請求,但只有當響應中包含特定措施(如CSRF令牌)時,才會信任這些請求。
令牌驗證:Django透過在檢視函式中新增一個名為get_response的裝飾器來實施CSRF保護。這個裝飾器會檢查請求中是否包含一個有效的CSRF令牌,該令牌在使用者與網站互動時由網站生成,並儲存在使用者的會話中。
非GET請求:對於不是GET、HEAD或OPTIONS的HTTP請求,Django預設會驗證CSRF令牌。這意味著任何表單提交、AJAX請求或其他型別的POST請求都需要包含CSRF令牌。
模板中的自動生成:Django模板系統會自動在表單中新增CSRF令牌,開發者在設計表單時無需手動新增。
自定義處理:開發者可以透過設定django.middleware.csrf.CsrfViewMiddleware來自定義CSRF保護的行為,例如,可以建立自己的CSRF保護策略或禁用CSRF保護。
總結來說,Django的CSRF保護是為了確保Web應用的安全性,防止攻擊者利用使用者的會話執行未授權的操作。
通常可利用裝飾器:
from django.views.decorators.csrf import csrf_protect, csrf_exempt
@ csrf_exempt關閉驗證
@ csrf_protect開啟驗證
目標:
Django的CSRF保護預設針對所有非GET、非HEAD、非OPTIONS的HTTP請求。這意味著,任何形式的表單提交(使用method="post"的HTML表單)、AJAX請求、或其他型別的POST、PUT、DELETE等請求都會受到CSRF保護。
具體來說,CSRF保護會檢查以下幾點:
POST請求:當使用者透過表單提交資料時,Django會檢查請求中是否包含正確的CSRF令牌。
AJAX請求:在使用JavaScript發起的AJAX請求中,需要在請求的頭部新增一個名為X-CSRFToken的HTTP頭來攜帶CSRF令牌。
PUT、DELETE等HTTP方法:對於使用這些HTTP方法的請求,Django同樣會驗證CSRF令牌。
非瀏覽器請求:對於非瀏覽器發起的請求(例如,由Python指令碼直接發起的請求),Django不會實施CSRF保護,因為這些請求通常不受同源策略的限制。
OPTIONS預檢請求:對於CORS(跨源資源共享)的OPTIONS預檢請求,Django不會驗證CSRF令牌,因為這些請求通常不攜帶任何有效載荷。
開發者可以自定義CSRF保護的行為,例如,可以透過設定django.middleware.csrf.CsrfViewMiddleware的process_view方法來改變預設的CSRF保護策略。此外,也可以透過設定django.middleware.csrf.CsrfViewMiddleware的exempt屬性來豁免某些檢視或URL路徑的CSRF保護。
總之,Django的CSRF保護是為了確保Web應用在面對跨站請求偽造攻擊時能夠保持安全,它透過驗證請求中的CSRF令牌來確保請求是由使用者預期的來源發出的。
2,Student模型Q查詢和普通get查詢有什麼區別?
語法:
# 假設有一個使用Q物件構建查詢的場景
query = Q(field1='value1') & Q(field2='value2')
results = query.all() # 這裡返回的是一個結果集的抽象表示
# 然後你可以使用get方法來獲取一個具體的記錄,如果存在的話
record = results.get() # 這會返回一個具體的記錄或者None
查詢返回結果
Q查詢結果是:
<class 'django.db.models.query.QuerySet'>
<QuerySet [<Student: Student object (7)>, <Student: Student object (8)>]>
返回的是一個模型類物件列表
get查詢結果是:
<class 'mysystem.models.Student'>
Student object (3)
返回的是一個模型類物件
方式:
get通常是查詢指定欄位
Q查詢可以構建複雜的查詢,
Q物件通常是指一個查詢構造器或者查詢物件,它允許開發者構建複雜的查詢語句。這樣的物件提供了鏈式呼叫的方法來指定查詢條件、排序、限制等。而get方法通常是在查詢構造完成後用來執行查詢並獲取結果的。
具體來說,Q物件構建的查詢返回的是一個查詢結果集的抽象表示,也就是一個包含了一系列符合條件的記錄的集合。這個集合可能包含了很多記錄,但是並沒有實際從資料庫中檢索出資料。
而get方法返回的是查詢結果集中的一個單獨的記錄。當你使用get方法時,通常指定了查詢返回的記錄的型別(例如,對於一個使用者表的查詢,你可能想要獲取一個User物件),然後查詢執行並返回該型別的一個例項。如果查詢結果集中有多個記錄,get方法通常會返回第一個記錄。
需要了解鏈式和非鏈式查詢區別,以及使用多條件和使用‘與或非’,
或: | 多個條件,一個為真全為真
與: &
非: 沒有直接的非,可以使用~取反
Student.objects.get(pk=id)
等效SELECT * FROM Student WHERE pk = id;
Student.objects.filter(Q(name=id) | Q(des=id))
等效SELECT * FROM Student WHERE name LIKE id OR des LIKE id;
建議:需要什麼就用什麼欄位,少用*,like查詢在沒有索引的情況下,可能效率較低
3,列表推導式怎麼用
[值物件,值範圍,判斷條件]
值物件:Python資料型別,包含int,str,list,(),{}等,需要插入構造列表的值
值範圍:相當於迴圈次數
判斷條件:符合則插入值物件中
results = [
{
'name': item.name,
'description': item.description
}
for item in instance
if item.age > 24
]
把可迭代物件instance中的item取出,當item.age > 24時,把另外兩個值寫入值物件 集合中
相當於下面虛擬碼:
results = [{'name','description'}]
for item in instance:
if item.age > 24:
results.append(item)
提供幾種常見的用法
- 列表推導式的執行順序:各語句之間是巢狀關係,左邊第二個語句是最外層,依次往右進一層,左邊第一條語句是最後一層。
>>> aList = [x*x for x in range(10)]
#相當於
>>> aList = []
>>> for x in range(10):
aList.append(x*x)
>>> freshfruit = [' banana', ' loganberry ', 'passion fruit ']
>>> aList = [w.strip() for w in freshfruit]
#等價於下面的程式碼
>>> aList = []
>>> for item in freshfruit:
aList.append(item.strip())
123456789101112
- 使用列表推導式實現巢狀列表的平鋪。
>>> vec = [[1, 2, 3], [4, 5, 6], [7, 8, 9]]
>>> [num for elem in vec for num in elem]
[1, 2, 3, 4, 5, 6, 7, 8, 9]
123
在這個列表推導式中有2個迴圈,其中第一個迴圈可以看作是外迴圈,執行的慢;而第二個迴圈可以看作是內迴圈,執行的快。上面程式碼的執行過程等價於下面的寫法:
>>> vec = [[1, 2, 3], [4, 5, 6], [7, 8, 9]]
>>> result = []
>>> for elem in vec:
for num in elem:
result.append(num)
>>> result
[1, 2, 3, 4, 5, 6, 7, 8, 9]
1234567
- 在列表推導式中使用if過濾不符合條件的元素。
在列表推導式中可以使用if子句對列表中的元素進行篩選,只在結果列表中保留符合條件的元素。下面的程式碼可以列出當前資料夾下所有Python原始檔:
>>> import os
>>> [filename for filename in os.listdir('.') if filename.endswith(('.py', '.pyw'))]
12
從列表中選擇符合條件的元素組成新的列表:
>>> aList = [-1, -4, 6, 7.5, -2.3, 9, -11]
>>> [i for i in aList if i>0] #所有大於0的數字
[6, 7.5, 9]
123
- 查詢列表中最大元素的所有位置。
>>> from random import randint
>>> x = [randint(1, 10) for i in range(20)]
#20個介於[1, 10]的整數
>>> x
[10, 2, 3, 4, 5, 10, 10, 9, 2, 4, 10, 8, 2, 2, 9, 7, 6, 2, 5, 6]
>>> m = max(x)
>>> [index for index, value in enumerate(x) if value == m]
#最大整數的所有出現位置
[0, 5, 6, 10]
123456789
- 在列表推導式中同時遍歷多個列表或可迭代物件。
>>> [(x, y) for x in [1, 2, 3] for y in [3, 1, 4] if x != y]
[(1, 3), (1, 4), (2, 3), (2, 1), (2, 4), (3, 1), (3, 4)]
12
對於包含多個迴圈的列表推導式,一定要清楚多個迴圈的執行順序或“巢狀關係”。例如,上面第一個列表推導式等價於
>>> result = []
>>> for x in [1, 2, 3]:
for y in [3, 1, 4]:
if x != y:
result.append((x,y))
>>> result
[(1, 3), (1, 4), (2, 3), (2, 1), (2, 4), (3, 1), (3, 4)]