drf框架
"""
接口:
接口規範:
drf生命週期:
序列化組件:
三大認證組件:
過濾、篩選、排序、分頁組件:
請求、響應、解析、異常模塊:
jwt:
"""
"""
http協議
應用層協議
請求與響應規範:首行 - 頭 - 體
特色:無狀態、無鏈接、請求永遠是客戶端到服務器端、ssl
wsgi協議
原生django啓動項目 - 啓動了server socket - wsgiref - uWSGI(項目上線)
規定數據的解析方式:
get數據、post數據(數據數據) => request => 回調的視圖函數
返回響應對象 - HTTPResponse類對象 - 數據、響應狀態碼
"""
接口
"""
url連接:http://api.oldboy.com/login/
請求方式:get | post | put ...
請求參數:username | password
響應結果:result | data
"""
"""
url連接如何書寫、請求到底採用什麼方式、規定哪些參數是必傳或是選填、到底響應什麼數據 => 接口規範
"""
restful接口規範
"""
1)通常都採用安全協議(接口都是操做數據的):https
2)體現接口的關鍵字:api
https://api.oldboy.com
https://www.oldboy.com/api
3)接口操做的數據稱之爲資源:採用資源名稱的複數
https://api.oldboy.com/books/
https://api.oldboy.com/users/
4)接口連接中不出現操做資源的動詞,經過請求方式來決定操做資源的動做
https://api.oldboy.com/books/
get:獲取全部 | post:增長一個
https://api.oldboy.com/books/(?P<pk>)/
get:獲取一個 | put:總體修改一個(patch:局部修改一個) | delet:刪除一個
5)資源數據有多版本時,接口能夠作版本控制
https://api.oldboy.com/books/v1/
https://api.oldboy.com/v2/books/
6)資源響應的限制條件:篩選、排序、限制...
https://api.oldboy.com/books/?publish=1&ordering=-price&limit=3
7)響應狀態碼
網絡狀態碼:2xx | 3xx | 4xx | 5xx
數據狀態碼(約定的):0 | 1 | 2
{
'status': 1,
}
-- SUCCESS(0, "查詢成功")
-- NODATA(1, "非正確,無數據,顯示基本信息")
-- FEAILED(2, "查詢失敗")
8)響應結果的信息描述:
{
'status': 1,
'msg': 'login failed'
}
9)響應的結果:get全部:全部資源 | get一個:一個資源 | post、put、patch:新增、修改的資源 | delete:不作任何返回
{
'status': 0,
'msg': 'ok',
'results': [登陸的用戶對象序列化結果]
}
10)響應結果中有二次資源(用戶頭像:圖片連接,用戶詳情:詳情接口)
要代表請求二次資源的接口
注:經過 接口文檔 告訴前臺傳遞的必要和選填參數
"""
百度測試接口
安裝postman
https://www.getpostman.com/downloads/
測試接口
method: GET
url: https://api.map.baidu.com/place/v2/search
params:
ak: 6E823f587c95f0148c19993539b99295
region: 上海
query: 肯德基
output: json
原生Django實現接口
建立Django項目並設置默認app名爲api,完成路由分發
# 主路由
from django.conf.urls import url, include
from django.contrib import admin
urlpatterns = [
url(r'^admin/', admin.site.urls),
url(r'^api/', include('api.urls')),
]
# api應用下的子路由
from django.conf.urls import url
from . import views
urlpatterns = [
# as_view() 本質拿到 view函數地址,
# view內部經過dispatch分發請求給具體的(get|post|delete)方法處理請求
# 處理完後的響應結果會一層層返回
url(r'^books/$', views.BookView.as_view()),
url(r'^books/(?P<pk>.*)/$', views.BookView.as_view()),
]
模型層:models.py
from django.db import models
class Book(models.Model):
name = models.CharField(max_length=64)
price = models.DecimalField(max_digits=5, decimal_places=2)
class Meta:
db_table = 'old_boy_book'
verbose_name = '書籍'
verbose_name_plural = verbose_name
def __str__(self):
return self.name
數據庫遷移
>: python manage.py makemigrations
>: python manage.py migrate
後臺管理:admin.py
from django.contrib import admin
from . import models
admin.site.register(models.Book)
admin.site.register(models.User)
# 建立超級用戶
# >: python manage.py createsuperuser
視圖層:views.py
from django.views import View
from django.http import JsonResponse
from . import models
class BookView(View):
def get(self, request, *args, **kwargs):
pk = kwargs.get('pk')
if pk: # 經過是否有主鍵決定獲取單個或是所有資源
book_dic_list = models.Book.objects.filter(pk=pk).values('name', 'price')
if not book_dic_list:
return JsonResponse({
'status': 2,
'msg': 'pk值有誤',
'results': {}
})
return JsonResponse({
'status': 0,
'msg': 'ok',
'results': book_dic_list[0]
})
book_dic_list = models.Book.objects.all().values('name', 'price')
if not book_dic_list:
return JsonResponse({
'status': 2,
'msg': '無數據',
'results': {}
})
return JsonResponse({
'status': 0,
'msg': 'ok',
'results': list(book_dic_list)
})
視圖層回顧
視圖:models.py
class User(models.Model):
SEX_CHOICES = [
(0, '男'),
(1, '女'),
(2, '哇塞')
]
username = models.CharField(max_length=64)
password = models.CharField(max_length=64)
sex = models.IntegerField(choices=SEX_CHOICES, default=0)
# 須要配置media工做目錄與路由
icon = models.ImageField(upload_to='icon', default='/icon/default.png')
class Meta:
db_table = 'old_boy_user'
verbose_name = '用戶'
verbose_name_plural = verbose_name
def __str__(self):
return self.username
# MEDIA_URL = '/media/'
MEDIA_ROOT = os.path.join(BASE_DIR, 'media')
路由:主urls.py
from django.conf.urls import url, include
from django.contrib import admin
from django.views.static import serve
from django.conf import settings
urlpatterns = [
url(r'^admin/', admin.site.urls),
url(r'^api/', include('api.urls')),
url(r'^media/(?P<path>.*)', serve, {'document_root': settings.MEDIA_ROOT})
]
drf框架
安裝
>: pip3 install djangorestframework
配置:settings.py
# 註冊drf app
NSTALLED_APPS = [
# ...
'rest_framework',
]
特色:
# 具體功能在具體模塊下
from rest_framework.request import Request
from rest_framework.response import Response
from rest_framework.exceptions import APIException
from rest_framework.filters import OrderingFilter
from rest_framework.views import APIView
from rest_framework.pagination import PageNumberPagination
from rest_framework.settings import APISettings
# 自定義drf配置 - 在本身的settings.py
REST_FRAMEWORK = {
# 自定義修改drf的配置們
}
原生Django CBV 源碼分析:View
"""
1)as_view()是入口,獲得view函數地址
2)請求來了調用view函數,內部調用dispatch函數完成請求分發
3)dispatch函數將請求方式映射成視圖類的同名方法,完成請求的處理,獲得相應
4)再將相應的結果一層層返回
"""
drf CBV 源碼分析:APIView
"""
1)as_view()是入口,獲得view函數地址,在範圍view函數地址時局部禁用csrf認證
2)請求來了調用view函數,內部調用(APIView類的)dispatch函數完成請求分發
3)dispatch函數 二次封裝request、完成三大認證後,再將請求方式映射成視圖類的同名方法,完成請求的處理,獲得相應,再對相應作渲染處理
4)再將相應的結果一層層返回
"""
響應渲染模塊:json和瀏覽器接口頁面
# 入口:APIView類的dispatch函數
self.response = self.finalize_response(request, response, *args, **kwargs)
->
neg = self.perform_content_negotiation(request, force=True)
->
renderers = self.get_renderers()
->
self.renderer_classes
->
APISetting:DEFAULT_RENDERER_CLASSES
局部配置
from rest_framework.views import APIView
from rest_framework.response import Response
from rest_framework.renderers import JSONRenderer
from rest_framework.renderers import BrowsableAPIRenderer
class UserAPIView(APIView):
# 局部配置:只有該視圖類起做用
renderer_classes = [JSONRenderer] # 只提供JSON數據渲染
pass
全局配置
# drf配置
REST_FRAMEWORK = {
# 響應的渲染模塊
'DEFAULT_RENDERER_CLASSES': [
'rest_framework.renderers.JSONRenderer',
'rest_framework.renderers.BrowsableAPIRenderer',
],
}
# 入口:APIView類的dispatch函數
request = self.initialize_request(request, *args, **kwargs)
->
parsers=self.get_parsers()
->
self.parser_classes
->
APISetting:DEFAULT_PARSER_CLASSES
局部配置
from rest_framework.views import APIView
from rest_framework.response import Response
from rest_framework.parsers import JSONParser
from rest_framework.parsers import FormParser
from rest_framework.parsers import MultiPartParser
class UserAPIView(APIView):
# 局部配置:只有該視圖類起做用
parser_classes = [JSONParser] # 只提供JSON解析
pass
全局配置
# drf配置
REST_FRAMEWORK = {
# 響應的渲染模塊
'DEFAULT_RENDERER_CLASSES': [
'rest_framework.renderers.JSONRenderer',
'rest_framework.renderers.BrowsableAPIRenderer',
],
# 請求數據解析模塊
'DEFAULT_PARSER_CLASSES': [
'rest_framework.parsers.JSONParser', # 'application/json'
'rest_framework.parsers.FormParser', # 'application/x-www-form-urlencoded'
'rest_framework.parsers.MultiPartParser' # multipart/form-data
],
}
請求數據解析位置
# 請求的數據包:均解析到 request.data 中
# 請求的?文件參數:均解析到 request.query_params 中
響應模塊
# 響應能夠設置響應數據、響應網絡狀態碼、響應頭、響應數據類型等
data = {
'status': 0,
'msg': 'get ok',
'results': [],
'token': '123.12321.231'
}
return Response(
data=data,
status=status.HTTP_200_OK,
headers={'Token': '123as.masd21.asd213sd'},
content_type='application/json' # 默認就是application/json
)