# 接口:url連接,經過向連接發送不一樣的類型請求與參數獲得相應的響應數據
# 1.在視圖層書寫處理請求的 視圖函數
# 2.在路由層爲視圖函數配置 url連接 => 產生接口
# 3.前臺經過ajax,爬蟲,工具等對接口發送請求,提交相應的參數得到對應的響應數據
# https://api.map.baidu.com/place/v2/search
'''
ak: 6E823f587c95f0148c19993539b99295
region: 上海
query: 肯德基
output: json
'''
# 定義接口的規範
# REST: 表徵性狀態轉移(Representational State Transfer)
# RESTful規範:web數據請求接口設計規範
# 學習的目的:
# 1.如何設計url連接地址
# 2.如何設計響應的數據格式
'''
1)一般使用https請求
2)域名:有api關鍵字出現
-- https://api.baidu.com (可能涉及跨越問題)
-- https://baidu.com/api
3)版本:不一樣版本須要標註
-- https://example.com/api/v1 | -- https://example.com/api/1
-- https://example.com/api/v2 | -- https://example.com/api/2
4)資源:請求的目標數據稱之爲資源,資源通常都用名詞複數表示
-- https://example.com/api/v1/books (以前不規範的案例: /get_books/)
5)操做方式:不從請求連接體現操做方式,從請求方式上決定操做方式
-- get:https://example.com/api/v1/books 獲取全部
-- post:https://example.com/api/v1/books 新增一本
-- put:https://example.com/api/v1/book/1 更新id=1的一本
-- patch:https://example.com/api/v1/book/1 更新id=1的一本
-- delete:https://example.com/api/v1/book/1 刪除id=1的一本
6)資源過濾:經過接口傳遞參數來過濾資源
-- https://example.com/api/v1/books?limit=10 限制10條
7)狀態碼:返回數據要標準狀態碼,經過在數據中 {"status": 0}
-- SUCCESS("0", "查詢成功")
-- NODATA("1xx", "非正確,無數據,顯示基本信息")
-- FEAILED("2xx", "查詢失敗")
8)錯誤信息:請求失敗須要標註錯誤信息 {"msg": "請求參數不合法"}
9)操做結果:請求操做成功的返回結果 {"results": []}
-- get:返回資源列表 | 返回單一資源
-- post:返回單一新增資源
-- put:返回更新的資源
-- patch:返回更新的資源
-- delete:返回空文檔
10)子資源返回資源接口:返回的資源若是有子資源,返回子資源的連接地址,如查找書,書的封面圖片就能夠url表示
'''
'''
1.url連接設計:採用https方式,有api關鍵字,有版本須要明確版本,請求連接用名詞來表示資源,具體的操做方式採用請求方式來肯定
2.url響應數據設計:須要明確 狀態碼、錯誤信息、成功結果,子資源通常用子資源的接口來標註
'''
# 路由層 from app import views urlpatterns = [ url(r'^books/', views.books), ] # 視圖層 from django.http import JsonResponse book_list = [{'id': 1, 'name': '紅樓夢'}, {'id': 2, 'name': '水滸傳'}] def books(request): if request.method == "GET": if 'ak' not in request.GET: return JsonResponse({ 'status': '101', 'msg': 'ak不存在' }, json_dumps_params={'ensure_ascii': False}) ak = request.GET.get('ak') if ak != '123abc': return JsonResponse({ 'status': '200', 'msg': 'ak非法' }, json_dumps_params={'ensure_ascii': False}) return JsonResponse({ 'status': '0', 'msg': 'ok', 'results': book_list }, json_dumps_params={'ensure_ascii': False}) if request.method == 'POST': name = request.POST.get('name') if not name: return JsonResponse({ 'status': '101', 'msg': '參數不合法', }, json_dumps_params={'ensure_ascii': False}) id = len(book_list) + 1 book = {'id': id, 'name': name} book_list.append(book) return JsonResponse({ 'status': '0', 'msg': 'ok', 'results': book }, json_dumps_params={'ensure_ascii': False})
"""
1) as_view()
-- Users.as_view()本質拿到view(request, *args, **kwargs)函數對象
2)view(request, *args, **kwargs)
-- return self.dispatch(request, *args, **kwargs)來完成請求的反射
3)dispatch(request, *args, **kwargs)
-- 完成具體的請求響應的分發
# 注:重寫dispatch是能夠在分發響應時,加入其它邏輯限制
"""
# 路由層
from app import views
urlpatterns = [
url(r'^users/', views.Users.as_view()),
]
# 視圖層
from django.views import View
class Users(View):
# 請求響應的分發
def dispatch(self, request, *args, **kwargs):
pass # 能夠對請求加以限制
result = super(Users, self).dispatch(request, *args, **kwargs)
pass # 能夠對請求再進一步處理
return result
def get(self, request, *args, **kwargs):
return JsonResponse({
"msg": 'get msg'
})
def post(self, request, *args, **kwargs):
name = request.POST.get('name')
print(name)
return JsonResponse({
"msg": 'post msg'
})
# pip3 install djangorestframework
# 1)安裝drf:pip3 install djangorestframework
# 2)settings.py註冊app:INSTALLED_APPS = [..., 'rest_framework']
# 3)基於cbv完成知足RSSTful規範的接口
from rest_framework.views import APIView
from rest_framework.request import Request
from rest_framework.response import Response
# 路由層 from app import views urlpatterns = [ url(r'^teachers/', views.Teachers.as_view()), ] # 視圖層 from rest_framework.views import APIView from rest_framework.response import Response class Teachers(APIView): def get(self, request, *args, **kwargs): salary = request.GET.get('salary') print(salary) return Response({ 'status': 2, 'msg': 'get請求成功', }) # 前臺發送數據的方式:formdate | urlencoded | json # drf的request都對其二次封裝解析到request.data中 def post(self, request, *args, **kwargs): salary = request.data.get('salary') print(salary) return Response({ 'status': 2, 'msg': 'post請求成功', })
# as_view() # 核心走了父類as_view view = super(APIView, cls).as_view(**initkwargs) # 返回的是局部禁用csrf認證的view視圖函數 return csrf_exempt(view) # dispatch(self, request, *args, **kwargs) # 二次封裝request對象 request = self.initialize_request(request, *args, **kwargs) # 自定義request規則 self.initial(request, *args, **kwargs) # initialize_request(self, request, *args, **kwargs) # 原生request封裝在request._request # initial(self, request, *args, **kwargs) # 認證 self.perform_authentication(request) # 權限 self.check_permissions(request) # 頻率 self.check_throttles(request) # 在drf的request.py的模塊中,對django的request進行二次封裝 def __getattr__(self, attr): try: return getattr(self._request, attr) except AttributeError: return self.__getattribute__(attr) # 完成對django的request徹底兼容
# models.py class Students(models.Model): name = models.CharField(max_length=32) age = models.IntegerField() gender = models.CharField(max_length=8) def __str__(self): return 'Student: %s' % self.name # 自定義序列化類:爲具體的類提供序列化 # my_serializer.py from rest_framework import serializers class StudentSerializer(serializers.Serializer): # 1.若是沒有source引入models的字段名,序列化字段名必須同models的字段名 # 2.若是有source引入models的字段名,序列化字段名必須不一樣於models的字段名,目的是對外隱藏數據庫的字段名 id = serializers.IntegerField() stu_name = serializers.CharField(source='name') age = serializers.IntegerField() gender = serializers.CharField() # views.py from app import models from app.my_serializer import StudentSerializer class Students(APIView): def get(self, request, *args, **kwargs): stus = models.Students.objects.all() # 須要序列化多個對象,須要明確many=True stu_ser = StudentSerializer(stus, many=True) print(stus) return Response({ 'status': 0, 'msg': 'ok', 'results': stu_ser.data }) # urls.py from app import views urlpatterns = [ url(r'^students/', views.Students.as_view()), ]
# 數據的傳輸與文件存儲均是採用字符串格式
# 序列化:將對象轉換成字符串的過程,進而用來傳輸或存儲
# 反序列化:將字符串轉換爲對象的過程,在程序中使用