Django&DRF重點內容大盤點
Django&DRF重點內容大盤點
本文只是將學習過程中需要深刻記憶,在工作中常用的一些命令或者知識點進行一個羅列並闡釋,不會全面的將所有內容進行講解。大家可以在瞭解了Django框架和DRF框架之後再來看這邊文章。否則會有點不知所云。
1.Django
1.1建立Django專案
這一命令必須熟記於心:
django-admin startproject 專案名
1.2 建立子應用
1.在工作中我們要開發很多專案,肯定需要很多模組,建立子應用肯定也需要掌握:
python manage.py startapp 子應用名
注意:此命令需要在專案的目錄下進行輸入。
2.建立完子應用中之後,千萬不要忘記去INSTALLED_APPS中進行註冊,這個引數在setting檔案中。
1.3一個程式注意的點
1.3.1檢視函式的定義
1)定義檢視函式之後,要有一個request形參接收請求物件。
2)返回的時候用到了HttpResponse
這一命令返回響應物件
1.3.2url地址的配置
1.在子應用中的urls.py檔案中設定當前子應用中url地址和檢視對應關係
urlpatterns = [ url(r'^url正則表示式$',views.檢視函式名) ]
2.在專案總的urls.py檔案中包含子應用中的urls.py檔案
urlpatterns = [ url(r'^',include('users.urls')) ]
1.4url配置
在子應用中進行url地址的配置時,建議嚴格匹配開頭和結尾,避免在地址匹配時候出錯。
1.5專案配置項
1.BASE_DIR指的是Django專案根目錄
2.語言和時區本地化:
LANGUAGE_CODE = 'zh-Hans' # 中文語言 TIME_ZONE = 'Asia/Shanghai' # 中國時間
1.6客戶端向伺服器傳遞引數途徑
1.6.1通過URL地址傳遞引數
在我們的url地址中的引數,我們如果想要獲取可以在子應用中的urls檔案中進行設定
/weather/城市/年份 url(r'weather/(?P<city>\w+)/(?P<year>\d{4})/$'views.weather)
1.6.2通過查詢字串傳遞引數
# /qs/?a=1&b=2&a=3 def qs(request): a = request.GET.get('a') b = request.GET.get('b') alist = request.GET.getlist('a') print(a)# 3 print(b)# 2 print(alist)# ['1', '3'] return HttpResponse('OK')
重要:查詢字串不區分請求方式,即假使客戶端進行POST方式的請求,依然可以通過request.GET獲取請求中的查詢字串資料。
1.6.3通過請求體傳遞資料
1)post表單提交的資料
/form/ def form_data(request): name = request.POST.get('name') age = request.POST.get('age') return HttpResponse('OK')
2)json資料
/json/ def json_data(request): req_data = request.body json_str = req_data.decode() req_dict = json.loads(json_str) name = req_dict.get('name') age = req_dict.get('age') return HttpResponse('OK')
1.6.4通過請求頭傳遞資料(瞭解即可)
1.6.5request物件的屬性
request請求物件的屬性 | 說明 |
---|---|
GET | 查詢字串引數 |
POST | 請求體重的表單資料 |
body | 請求體中原始的bytes資料 |
method | 請求方式 |
path | 請求的url路徑 |
META | 請求頭 |
COOKIES | 客戶端傳送的cookie資訊 |
FILES | 客戶端上傳的檔案 |
1.7相應物件構造
1.7.1響應時返回json資料
def get_json(request): res_dict = { 'name':'xiaoyan', 'age':'18' } return JsonResponse(res_dict)
1.7.2響應時進行頁面重定向
def redirect_test(request): # 第一個引數是namespace,第二個引數是name req_url = reverse('users:index') return redirect(req_url)
1.8狀態保持之session
1)將session資訊儲存到redis中
CACHES = { "default": { "BACKEND": "django_redis.cache.RedisCache", "LOCATION": "redis://127.0.0.1:6379/1", "OPTIONS": { "CLIENT_CLASS": "django_redis.client.DefaultClient", } } } SESSION_ENGINE = "django.contrib.sessions.backends.cache" SESSION_CACHE_ALIAS = "default"
2)設定session
request.session['<key>'] = '<value>'
3)獲取session
request.session.get('<key>')
1.9類檢視
1.9.1類檢視的使用
1)定義類檢視
/register/ class RegisterView(View): def get(self,request): return HttpResponse('返回註冊頁面') def post(self,request): return HttpResponse('進行註冊處理...') def put(self,request): return HttpResponse('put方法被呼叫')
2)進行url配置
url(r'^register/$',views.RegisterView.as_view())
1.9.2類檢視新增裝飾器
使用Django框架提供method_decorator將針對函式檢視裝飾器新增到類檢視的方法上面
# 為全部請求方法新增裝飾器 @method_decorator(my_decorator, name='dispatch') class DemoView(View): def get(self, request): print('get方法') return HttpResponse('ok') def post(self, request): print('post方法') return HttpResponse('ok') # 為特定請求方法新增裝飾器 @method_decorator(my_decorator, name='get') class DemoView(View): def get(self, request): print('get方法') return HttpResponse('ok') def post(self, request): print('post方法') return HttpResponse('ok')
1.10中介軟體
1.10.1定義中介軟體
def simple_middleware(get_response): # 此處編寫的程式碼僅在Django第一次配置和初始化的時候執行一次。 def middleware(request): # 此處編寫的程式碼會在每個請求處理檢視前被呼叫。 response = get_response(request) # 此處編寫的程式碼會在每個請求處理檢視之後被呼叫。 return response return middleware
1.10.2 在MIDDLEWARE
中註冊中間
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', 'users.middleware.my_middleware',# 新增中介軟體 ]
1.10.3注意:中介軟體是全域性的
1.11使用模板的詳細步驟
1.載入模板:指定使用模板檔案,獲取模板物件
from django.template import loader temp = loader.get_template('模板檔名')
2.模板渲染:給模板檔案傳遞變數,將模板檔案中的變數進行替換,獲取替換之後的html內容
res_html = temp.render(字典)
3.建立響應物件
return HttpResponse(res_html)
1.12資料庫
1.12.1資料庫連結配置
1.在settings.py進行配置
DATABASES = { 'default': { 'ENGINE': 'django.db.backends.mysql', 'HOST': '127.0.0.1',# 資料庫主機 'PORT': 3306,# 資料庫埠 'USER': 'root',# 資料庫使用者名稱 'PASSWORD': 'mysql',# 資料庫使用者密碼 'NAME': 'django_demo'# 資料庫名字 } }
2.首次啟動時需要在專案同名的目錄init .py新增
pip install pymysql
import pymysql pymysql.install_as_MySQLdb
1.12.2定義模型類
class 模型類名(models.Model): # 欄位名 = models.欄位型別(選項引數) # ... class Meta: db_table = '<表名>'
定義外來鍵屬性
hbook = models.ForeignKey(BookInfo, on_delete=models.CASCADE, verbose_name='圖書')# 外來鍵
cascade是級聯,刪除主表資料時連同外來鍵表中資料一起刪除
1.12.3遷移生成表
1)生成遷移檔案
python manage.py makemigrations
2)同步到資料庫中
python manage.py migrate
1.12.4通過模型類和物件進行資料庫操作(增刪改查)
新增:
- 建立模型類物件-->物件.save()
注意:新增HeroInfo時,可以給hbook賦值,也可以直接表中hbook_id賦值
HeroInfo是定義的英雄模型類,與圖書BookInfo對應。
- 模型類.objects.create(...)
修改:
1. 查詢物件->修改物件屬性->物件.save() 2. 模型類.objects.filter(...).update(...)
刪除:
- 查詢物件->物件.delete()
- 模型類.objects.filter(...).delete()
查詢:
基本查詢 模型類.objects.查詢函式 條件查詢 對應get, filter, exclude引數中可以寫查詢條件 格式: 屬性名__條件名=值 注意:可以寫多個查詢條件,預設是且的關係 F物件 用於查詢時欄位之間的比較 from django.db.models import F Q物件 用於查詢時條件之間的邏輯關係 from django.db.models import Q &(與) |(或) ~(非) 聚合 聚合類: from django.db.models import Count, Sum, Avg, Max, Min aggregate 排序 排序預設是升序,降序在排序欄位前加- order_by 關聯查詢 1. 查詢和指定物件關聯的資料 由1查多 一物件.多類名小寫_set.all() 例:book.heroinfo_set.all() 由多查1 多物件.外來鍵屬性 例:hero.hbook 2. 通過模型類進行關聯查詢 查圖書(一) 一類.objects.get|filter(多類名__欄位__條件=值) 例:books = BookInfo.objects.filter(heroinfo__hcomment__contains='八') 查英雄(多) 多類.objects.filter(外來鍵屬性__欄位__條件=值) 例:heros = HeroInfo.objects.filter(hbook__bread__gt=30)
1.13admin站點
上傳圖片
Django自帶檔案儲存系統,可以直接通過Admin站點進行圖片的上傳,預設上傳的檔案儲存在伺服器本地。
使用
1)在配置檔案中設定配置項MEDIA_ROOT='上傳檔案的儲存目錄'
2)定義模型類時,圖片欄位的型別使用ImageField
3)遷移生成表並在admin.py註冊模型類,直接登入Admin站點就可以進行圖片上傳
2.DRF框架
2.1目的
利用DRF框架快速的實現RestAPI介面的設計
2.2RestfulAPI介面設計風格
關鍵點
1)url地址儘量使用名詞,不要使用動詞
2)請求url地址採用不同的請求方式執行不同的操作
GET(獲取)
POST(新增)
PUT(修改)
DELETE(刪除)
3)過濾引數可以放在查詢字串中
4)響應資料返回&響應狀態碼
狀態碼 | 說明 |
---|---|
200 | 獲取或修改成功 |
201 | 新增成功 |
204 | 刪除成功 |
404 | 資源不存在 |
400 | 客戶請求有誤 |
500 | 伺服器錯誤 |
5)響應資料的格式:json
2.3django自定義RestAPI介面
RestAPI介面核心工作
1.將資料庫資料序列化為前端所需要的格式,並返回
2.將前端傳送的資料反序列化為模型類物件,並儲存到資料庫中
2.4DRF框架
2.4.1作用:大大提高RestAPI介面開發效率
2.5序列化器Serializer
2.5.1功能
進行資料的序列化和反序列化
2.5.2序列化器的定義
繼承自serializers.Serializer
from rest_framework import serializers # serializers.Serializer:DRF框架中所有序列化器的父類,定義序列化器類時,可以直接繼承此類 # serializers.ModelSerializer:Serializer類的子類,在父類的基礎山,新增一些功能 class 序列化器類名(serializers.Serializer): # 欄位名 = serializers.欄位名(選項引數)
序列化器物件建立:
序列化器類(instance=<例項物件>,data=<資料>,**kwargs)
2.5.3序列化功能
說白了就是將例項物件轉換為字典資料
1)序列化單個物件
book = BookInfo.objects.get(id=1) serializer = BookInfoSerializer(book) res = json.dumps(serializer.data,ensure_ascii=False,indent=4)
2)序列化多個物件,其實就是添加了一個many引數
books = BookInfo.objects.all() serializer = BookInfoSerializer(books,many=True) res = json.dumps(serializer.data,ensure_ascii=False,indent=4)
3)關聯物件的巢狀序列化
1.將關聯物件序列化為關聯物件的主鍵
hbook = serializers.PrimaryKeyRelatedField(label='圖書',read_only=True)
2.採用指定的序列化器將關聯物件進行序列化
hbook = BookInfoSerializer(label='圖書')
3.將關聯物件序列化為關聯物件模型類_str _方法的返回值
hbook = serializers.StringRelatedField(label='圖書')
注意:和物件關聯的物件如果有多個,在序列化器中定義巢狀序列化欄位時,需要新增many=True。
2.5.4反序列化功能
反序列化-資料校驗:
data = {'btitle':'python','bpub_date':'1980-1-1'} serializer = BookInfoSerializer(data) serializer.is_valid() serializer.errors serialiser.validated_data
當系統提供的校驗不能滿足我們的需求的時候,我們可以補充額外的驗證:
1)指定特定欄位的validators
引數進行補充驗證
btitle = serializers.CharField(label='標題',max_length=20,validators=[about_django])
注意:此處的about_django
為我們自定義的校驗函式
2)在序列化器類中定義特定方法validate_<fieldname>
針對特定欄位進行補充驗證
def validate_btitle(self,value): if 'django' not in value.lower(): raise serializers.validationError('圖書不是關於Django的') return value
3)定義validate
方法進行補充驗證(結合多個欄位內容驗證)
def validate(self,attrs): """ 此處的attrs是一個字典,建立序列化器物件時,傳入data資料 """ bread = attrs['bread'] bcomment = attrs['bcomment'] if bread<=bcomment: raise serializers.ValidationError('圖書閱讀量必須大於評論量') return attrs
2.5.5反序列化-資料儲存(新增&更新)
校驗通過之後,可以呼叫serializer.save()
進行資料儲存
1)資料新增
def create(self,validated_data): """ validated_data:字典,校驗之後的資料 """ book = BookInfo.objects.create(**validated_data) return book ------------------------------------ data = {'btitle':'python','bpub_data':'1802-1-1','bread':30,'bcomment:20'} serializer = BookInfoSerializer(data=data) serializer.is_valid() serializer.save() serializer.data
2)資料更新
def update(self,instance,validated_data): """ instance:建立序列化器物件時傳入例項物件 validated_data:是一個字典,校驗之後的資料 """ btitle = validated_data.get('btitle') bpub_data_date = validated_data.get('bpub_date') instance.btitle = btitle instance.bpub_date = bpub_date instance.save() return instance
2.5.6使用序列化器改寫RestAPI介面
我們舉兩個代表性的例子即可:
# /books/ class BookListView(View): def get(self, request): """ 獲取所有的圖書的資訊: 1. 查詢所有的圖書的資料 2. 返回所有圖書的json的資料 """ # 1. 查詢所有的圖書的資料 books = BookInfo.objects.all() # QuerySet # 2. 返回所有圖書的json的資料,狀態碼: 200 books_li = [] for book in books: # 將book物件轉換成dict book_dict = { 'id': book.id, 'btitle': book.btitle, 'bpub_date': book.bpub_date, 'bread': book.bread, 'bcomment': book.bcomment, 'image': book.image.url if book.image else '' } books_li.append(book_dict) return JsonResponse(books_li, safe=False) def post(self, request): """ 新增一本圖書的資訊: 1. 獲取引數btitle和bpub_date並進行校驗 2. 建立圖書資訊並新增進資料表中 3. 返回新增的圖書的json資料,狀態碼: 201 """ # 需求: 前端需要傳遞新增圖書的資訊(btitle, bpub_date),通過json傳遞 # 1. 獲取引數btitle和bpub_date並進行校驗 # 獲取json的原始資料 req_data = request.body # bytes # 將bytes轉換為str json_str = req_data.decode() # 將json字串轉換dict req_dict = json.loads(json_str) # 獲取btitle和bpub_date btitle = req_dict.get('btitle') bpub_date = req_dict.get('bpub_date') # TODO: 省略引數校驗過程... # 2. 建立圖書資訊並新增進資料表中 book = BookInfo.objects.create( btitle=btitle, bpub_date=bpub_date ) # 3. 返回新增的圖書的json資料,狀態碼: 201 # 將book物件轉換成dict book_dict = { 'id': book.id, 'btitle': book.btitle, 'bpub_date': book.bpub_date, 'bread': book.bread, 'bcomment': book.bcomment, 'image': book.image.url if book.image else '' } return JsonResponse(book_dict, status=201)
修改之後:
class BookListView(View): def get(self, request): books = BookInfo.objects.all() # QuerySet serializer = BookInfoSerializer(books, many=True) return JsonResponse(serializer.data, safe=False) def post(self, request): req_data = request.body # bytes json_str = req_data.decode() req_dict = json.loads(json_str) serializer = BookInfoSerializer(data=req_dict) serializer.is_valid(raise_exception=True) # 反序列化-資料儲存(新增) -> create serializer.save() return JsonResponse(serializer.data, status=201)