DRF–day1
1. 前置概念
前后端分离
- 后端为前端项目返回所需的数据,不再进行页面的渲染,不再控制前端样式的效果
- 无论前端项目app|网站,后端都只需提供前端所需的数据
- 前后端分离的模式下,不再有render或redirect,对外一律提供API数据(json|xml)
- 前端与后端两个独立的项目全部通过ajax请求进行交互
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-bQINQFKN-1605052650191)(DRF–day1.assets/image-20200628100122921.png)]
接口API
- 接口就是一些预定好的函数或方法 ,目的是为了提供应用程序与开发人员基于软件|硬件访问一组数据的能力,但无需访问源码或理解我内部的原理
- 接口在web开发中是前后端工程师进行数据交互的媒介
- 在web开发的过程中,接口就是由 url地址、请求参数、响应数据组成
RESTFul架构
在长期的前后端分离的开发模式下,为了提高开发效率,大家都默认遵从了一种 REST规范,它提供了一套接口定义的良好的格式
1. RESTFul是一种软件架构风格、设计风格,而不是标准,只是提供了一组设计原则与约束条件。不是必须遵从的,但有了它之后可以更好的开发出简介、逻辑清晰的接口
2. 只要遵从了REST规范设计的软件就是RESTFul架构
3. 前后端分离模式下建议使用RESTFul风格,但只是一种设计规范,可以不遵守
RESTFul规范
核心目的:设计出更优雅的url
- API与用户的通信尽量使用HTTPS协议
- 每一个url用来标识一个唯一的资源
传统url: https://127.0.0.1/user/get_user/?id=3 代表用户id为5的用户信息
rest Url:https://127.0.0.1/user/get_user/1/ 代表用户id为1的用户信息
- 请求方法
1. GET : 从服务器获取资源 查询
2. POST:在服务器新增资源 添加
3. PUT:更新服务器资源 修改
4. DELETE:删除服务器资源 删除
5. PATCH:更新部分资源 局部修改
- 状态码
# 每一个http请求都会返回对应的状态信息,而RESTFul要求在返回数据时提供本次请求的状态码
# 返回的数据格式也有一定的要求
# 包含请求信息
- 接口API的本质
# RESTFul就是为了设计一个良好的接口,而大家都遵从这些默认的规范可以节省大量的时间
1. 后端接受一个包含参数的url
2. 解析参数,并对请求做相应的处理
3. 将处理后的结果序列化成json
4. 按照一定的格式将数据返回到前端
2. 工具使用
Postman的使用
接口测试工具:可以帮助开发者模拟发送各种http请求以及参数
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-j2HmdBpr-1605052650194)(DRF–day1.assets/image-20200628112641573.png)]
CSRF装饰器
from django.utils.decorators import method_decorator
from django.views.decorators.csrf import csrf_exempt, csrf_protect
# 函数视图
1. @csrf_protect # 全局禁用csrf的情况 为某个视图单独添加csrf认证
2. @csrf_exempt # 为某个视图免除csrf认证
# 类视图
1. @method_decorator(csrf_exempt, name="dispatch") # 让类视图免除csrf认证
1. @method_decorator(csrf_protect, name="dispatch") # 让类视图添加csrf认证
Navicat连接sqllite
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-Ot1YUKUY-1605052650195)(DRF–day1.assets/image-20200628120110045.png)]
3. Django开发接口API
接口开发
- urls
from django.urls import path
from app import views
urlpatterns = [
# 类视图url的定义
path("users/", views.UserView.as_view()),
# 匹配携带参数的路由
path("users/<str:id>/", views.UserView.as_view()),
]
- Views.py
- django类视图可以通过请求的http方法的不同来匹配不同的函数执行
- url中的参数可使用kwargs.get(“参数名”)的形式获取
- 接口API在返回数据的时候需要指定数据的格式以及状态码
@method_decorator(csrf_exempt, name="dispatch") # 让类视图免除csrf认证
class UserView(View):
"""
类视图内部通过请求的方法来匹配到对应的内部的函数,从而进行对应的处理
"""
def get(self, request, *args, **kwargs):
"""
提供查询单个用户与多个用户的操作
:param request: 用户id
:return: 查询后的用户信息
"""
# 获取用户的id
user_id = kwargs.get("id")
if user_id: # 查询单个
user_val = User.objects.filter(pk=user_id).values("username", "password", "gender").first()
if user_val:
# 如果查询出对应的用户信息,则将用户的信息返回到前端
return JsonResponse({
"status": 200,
"message": "查询单个用户成功",
"results": user_val
})
else:
# 如果没有传参数id 代表查询所有
user_list = User.objects.all().values("username", "password", "gender")
print(type(user_list))
if user_list:
return JsonResponse({
"status": 200,
"message": "查询所有用户成功",
"results": list(user_list),
})
return JsonResponse({
"status": 500,
"message": "查询失败",
})
def post(self, request, *args, **kwargs):
"""
新增单个用户
"""
username = request.POST.get("username")
pwd = request.POST.get("password")
try:
user_obj = User.objects.create(username=username, password=pwd)
return JsonResponse({
"status": 201,
"message": "创建用户成功",
"results": {"username": user_obj.username, "gender": user_obj.gender}
})
except:
return JsonResponse({
"status": 500,
"message": "创建用户失败",
})
Django类视图源码
- 类视图中源码的入口是url中的
as_view()
方法,通过此方法处理传递过来的类视图对象- 经过一系列处理后,调用
dispatch
方法进行视图的分发,进而匹配到类视图中对应的函数
# Django 请求流程总结
1. 前端发起访问请求,通过url匹配到对应的类视图
2. 类视图调用as_view()方法进行解析
3. 在as_view中实例化当前类视图为self
4. self对象 调用dispatch方法进行视图的分发
5. 在dispatch内部匹配到对应的类视图中的函数,执行对应的函数方法
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-gBgv6Q7I-1605052650196)(DRF–day1.assets/image-20200628150121414.png)]
4. DRF初识
DRF全称
DjangoRestFramework
,是一个灵活强大的工具包,主要是用来构建RESTFul风格的web API,它是Django生态中默认的前后端分离开发的标准官网:
https://www.django-rest-framework.org/
Github:
https://github.com/encode/django-rest-framework
DRF的搭建
# REST framework 需要以下内容:
Python (3.5, 3.6, 3.7, 3.8)
Django (1.11, 2.0, 2.1, 2.2, 3.0)
# 安装DRF
pip install djangorestframework==3.10.0
# 配置settings (必须)
INSTALLED_APPS = [
...
'rest_framework',
]
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-8Hy5tTw9-1605052650199)(DRF–day1.assets/image-20200628155006858.png)]
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-jz6BQo8F-1605052650200)(DRF–day1.assets/image-20200628160333884.png)]
DRF的第一个案例
- DRF的
APIView
继承了django的View类,所以DRF的请求分发是调用了继承的父类的方法,本身并没有做实现- DRF的视图最后返回了一个免除csrf认证的视图
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-hxwVkR5Q-1605052650200)(DRF–day1.assets/image-20200628161419865.png)]
from rest_framework.views import APIView
from rest_framework.response import Response
# 开发基于drf的视图
class UserAPIView(APIView):
def get(self, request, *args, **kwargs):
print("DRF GET VIEW")
return Response("DRF GET SUCCESS")
def post(self, request, *args, **kwargs):
print("POST GET VIEW")
return Response("POST GET SUCCESS")
DRF请求的生命周期
- DRF视图同样是在url中的as_view()方法作为入口,执行的是
APIView
中的as_view- 在
APIView
类中的as_view方法中调用了父类(django)
的as_view方法,APIView在最后返回了一个禁用csrf后的view- 在父类的as_view方法中调用了
self.dispatch()
方法进行请求的分发,由于子类自己实现了dispatch
方法,所以走子类自己的方法APIView
类中的dispatch
方法- DRF的
dispatch
方法进行了额外的功能的实现- 完成处理后交给类属图进行逻辑的处理,得到响应的结果后返回到前台。
- DRF核心dispatch方法
# DRF的核心类
def dispatch(self, request, *args, **kwargs):
"""
`.dispatch()` is pretty much the same as Django's regular dispatch,
but with extra hooks for startup, finalize, and exception handling.
"""
# 将参数赋值给实例化对象
self.args = args
self.kwargs = kwargs
# TODO DRF的请求模块 处理drf请求相关的
request = self.initialize_request(request, *args, **kwargs)
self.request = request
self.headers = self.default_response_headers # deprecate?
try:
# 三大认证模块
self.initial(request, *args, **kwargs)
# Get the appropriate handler method
if request.method.lower() in self.http_method_names:
handler = getattr(self, request.method.lower(),
self.http_method_not_allowed)
else:
handler = self.http_method_not_allowed
response = handler(request, *args, **kwargs)
except Exception as exc:
# 异常的捕获 一旦发生异常 在此处理
response = self.handle_exception(exc)
# 响应模块
self.response = self.finalize_response(request, response, *args, **kwargs)
return self.response
5. Request模块
主要功能:用来获取不同请求的参数
入口:request = self.initialize_request(request, *args, **kwargs)
Request类
class Request:
def __init__(self, request, parsers=None, authenticators=None,
negotiator=None, parser_context=None):
assert isinstance(request, HttpRequest), (
.format(request.__class__.__module__, request.__class__.__name__)
)
# request是django原生的请求对象 赋值给 DRF视图类对象作为属性 _request
# self当前 DRF视图类对象
self._request = request
self.parsers = parsers or ()
self.authenticators = authenticators or ()
self.negotiator = negotiator or self._default_negotiator()
self.parser_context = parser_context
self._data = Empty
self._files = Empty
self._full_data = Empty
self._content_type = Empty
self._stream = Empty
DRF获取GET请求参数
class UserAPIView(APIView):
def get(self, request, *args, **kwargs):
# request:<rest_framework.request.Request>
# get(self, request, *args, **kwargs): DRF视图中的request事 经过封装后的request对象 其中包含原生的request
# 可以通过_request 访问Django原生的request对象
print(request._request.GET) # 不推荐 知道即可
# 通过DRF 的request对象获取参数
print(request.GET)
# 通过quer_params来获取参数 DRF扩展的
print(request.query_params)
# 获取路径传参
user_id = kwargs.get("pk")
return Response("DRF GET SUCCESS")
DRF获取POST请求参数
post请求中,不同格式的参数要通过不同的形式接收
class UserAPIView(APIView):
def post(self, request, *args, **kwargs):
# post请求传递参数的形式 form-data www-urlencoded json
print(request._request.POST) # Django 原生的request对象
print(request.POST) # DRF 封装后的request对象
# 可以获取多种格式的参数 DRF 扩展的请回去参数 兼容性最强
print(request.data)
return Response("POST GET SUCCESS")
作业
1. 掌握django开发接口的方式,DRF开发接口的方法
完成 查询单个用户的API 查询所有用户API 必做
删除单个用户 修改单个用户 选做
2. 掌握django类视图请求流程
3. 掌握DRF视图请求源码流程
4. 掌握DRF获取参数的方式