django原生FBV

腿哥123發表於2024-04-03

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)]

相關文章