Python之路(三十四):Django rest freamwork (下)
后续
'''
1.request和response
DRF的request是Parser解析器处理过的请求
request.data : POST,PUT,PATCH,表单,json
request.query_params : ?后边的参数
DRF的response是Renderer渲染器处理过的响应
需要在settings中加入配置:
REST_FRAMEWORK = {
'DEFAULT_RENDERER_CLASSES': ( # 默认响应渲染类
'rest_framework.renderers.JSONRenderer', # json渲染器
'rest_framework.renderers.BrowsableAPIRenderer', # 浏览API渲染器
)
}
使用:Response(data, status=None, template_name=None, headers=None, content_type=None) data:字典(序列化后的数据)
常用属性:
response.data:传给response对象的序列化后,但尚未render处理的数据
response.status_code:状态码
response.context:经过render处理后的响应数据
有个状态码常量模块
'''
'''
2.类视图
提供一堆类视图APIView子类,就是不断继承重新,为了使用特定的方法
2-1.APIView类:(继承于django的View)
继承问题: django是继承View,现在DRF是继承APIView,Parses解释器和Renderer渲染器对request和response对象的构建,是APIView类来实现的
特点:
任何APIException异常都会被捕获到,并且处理成合适的响应信息;
在进行dispatch()分发前,会对请求进行身份认证、权限检查、流量控制
即可以自定义的属性: authentication_classes 列表或元祖,身份认证类
permissoin_classes 列表或元祖,权限检查类
throttle_classes 列表或元祖,流量控制类
2-2.GenericAPIView类:(继承于APIView)
增加了对于列表视图和详情视图可能用到的通用支持方法。通常使用时,可搭配一个或多个Mixin扩展类。
可以自定义的属性:
列表视图与详情视图通用:
queryset 列表视图的查询集
serializer_class 视图使用的序列化器
列表视图使用:
pagination_class 分页控制类
filter_backends 过滤控制后端
详情页视图使用:
lookup_field 查询单一数据库对象时使用的条件字段,默认为'pk'
lookup_url_kwarg 查询单一数据时URL中的参数关键字名称,默认与look_field相同
可以自定义的方法:
列表视图与详情视图通用:
get_queryset(self) 返回视图使用的查询集
get_serializer_class(self) 返回序列化器类
get_serializer(self, args, *kwargs) 返回序列化器对象
详情视图使用:
get_object(self) 返回详情视图所需的模型类数据对象
# url(r'^books/(?P<pk>\d+)/$', views.BookDetailView.as_view()), 当具体查某一本书的时候
class BookDetailView(GenericAPIView):
queryset = BookInfo.objects.all()
serializer_class = BookInfoSerializer
def get(self, request, pk): 书籍详情页
book = self.get_object() 根据pk找到需要的对象
serializer = self.get_serializer(book) 把书的对象传到序列化器中
return Response(serializer.data)
3.扩展类:
3-1.ListModelMixin: list方法会对数据进行过滤和分页
class BookListView(ListModelMixin, GenericAPIView): 和django的Mixin扩展类继承相同
queryset = BookInfo.objects.all()
serializer_class = BookInfoSerializer
def get(self, request):
return self.list(request)
3-2.CreateModelMixin : create方法快速实现创建资源的视图,成功返回201,数据验证失败400错误
3-3.RetrieveModelMixin : retrieve方法返回一个存在的数据对象,存在,返回200, 否则返回404
def get(self, request, pk):
return self.retrieve(request)
3-4.UpdateModelMixin : update方法更新一个存在的数据对象
partial_update局部更新, 成功返回200,序列化器校验数据失败时,返回400错误
3-5.DestroyModelMixin : destroy方法删除一个存在的数据对象,成功返回204,不存在返回404
还有几个子类视图,就是把GenericAPIView和Mixin功能写一起了,看讲义
'''
'''
3.视图集ViewSet
list() 提供一组数据
retrieve() 提供单个数据
create() 创建数据
update() 保存数据
destory() 删除数据
action行为:
url(r'^books/$', BookInfoViewSet.as_view('get', 'list')), get方法获取所有书籍-> list方法
url(r'^books/(?P<pk>\d+)/$', BookInfoViewSet.as_view('get', 'retrieve'))
常用视图集父类:
ViewSet(继承自APIView):提供了身份认证、权限校验、流量管理等
GenericViewSet(继承自GenericAPIView)
ModelViewSet(继承自GenericAPIVIew,同时包括了所有5个扩展)
ReadOnlyModelViewSet(继承自GenericAPIVIew,同时包括了ListModelMixin、RetrieveModelMixin)
自定义action:
action装饰器: methods 支持的请求方式,列表传递,
detail action中要处理的是否是视图资源的对象(即是否通过url路径获取主键)\
True 表示使用通过URL获取的主键对应的数据对象
False 表示不使用URL获取主键
# detail为False 表示不需要处理具体的BookInfo对象
@action(methods=['get'], detail=False)
def latest(self, request):
"""
返回最新的图书信息
"""
book = BookInfo.objects.latest('id')
serializer = self.get_serializer(book)
return Response(serializer.data)
# detail为True,表示要处理具体与pk主键对应的BookInfo对象
@action(methods=['put'], detail=True)
def read(self, request, pk):
"""
修改图书的阅读量数据
"""
book = self.get_object()
book.bread = request.data.get('read')
book.save()
serializer = self.get_serializer(book)
return Response(serializer.data)
url(r'^books/latest/$', views.BookInfoViewSet.as_view({'get': 'latest'})),
url(r'^books/(?P<pk>\d+)/read/$', views.BookInfoViewSet.as_view({'put': 'read'})),
限制Api访问速率
REST_FRAMEWORK = {
'DEFAULT_AUTHENTICATION_CLASSES': (
'rest_framework.authentication.SessionAuthentication',
'rest_framework.authentication.BasicAuthentication',
),
'DEFAULT_THROTTLE_CLASSES': (
'rest_framework.throttling.AnonRateThrottle',
'rest_framework.throttling.UserRateThrottle'
),
'DEFAULT_THROTTLE_RATES': {
'anon': '100/day',
'user': '1000/day'
}
}
Github
Xadmin
Ueditor
drf-jwt验证
django有现成的jwt轮子 django-rest-framework-jwt,可以拿来使用。
pip install djangorestframework-jwt
# drf全局设置
REST_FRAMEWORK = {
'DEFAULT_AUTHENTICATION_CLASSES': (
'rest_framework.authentication.SessionAuthentication',
'rest_framework.authentication.BasicAuthentication',
),
}
# jwt 过期时间设置
import datetime
JWT_AUTH = {
'JWT_AUTH_HEADER_PREFIX': 'JWT',
'JWT_EXPIRATION_DELTA': datetime.timedelta(days=7),
}
# URL
re_path(r'^login/', obtain_jwt_token),
也可以在指定的ViewSet下设置权限,比如对商品信息做权限认证,需登录后才能获得信息。
queryset = ShoppingCart.objects.all()
serializer_class = ShoppingSerializer
permission_classes = (IsAuthenticated, permissions.IsOwnerOrReadOnly) # 必须登录, 必须是用户本人
authentication_classes = (JSONWebTokenAuthentication, SessionAuthentication) # jwt验证和session验证
users.views中新建backend,对用户名或手机进行验证
from django.contrib.auth.backends import ModelBackend from
django.contrib.auth import get_user_model
from django.db.models import Q
User = get_user_model()
class CustomBackend(ModelBackend):
def authenticate(self, request, username=None, password=None, **kwargs):
try:
user = User.objects.get(Q(username=username) | Q(mobile=username))
if user.check_password(password):
return user
except Exception as e:
return None
设置认证backend
settings 中添加
AUTHENTICATION_BACKENDS = { 'users.views.CustomBackend' }
# 创建用户时携带token (重写create方法)
def create(self, request, *args, **kwargs):
serializer = self.get_serializer(data=request.data)
serializer.is_valid(raise_exception=True)
user = self.perform_create(serializer)
re_dic = serializer.data
payload = jwt_payload_handler(user)
re_dic['token'] = jwt_encode_handler(payload)
headers = self.get_success_headers(serializer.data)
return Response(re_dic, status=status.HTTP_201_CREATED, headers=headers)
django-crosheaders
pip install django-cors-headers
然后将其添加到已安装的应用程序中:
-
INSTALLED_APPS =(
-
...
-
' corsheaders ',
-
...
-
)
还需要添加一个中间件类来收听响应:
-
MIDDLEWARE = [ #或MIDDLEWARE_CLASSES on Django <1.10
-
...
-
' corsheaders.middleware.CorsMiddleware ',
-
' django.middleware.common.CommonMiddleware ',
-
...
-
]
CorsMiddleware应该放置得尽可能高,特别是在可以产生响应的任何中间件之前, 如Django CommonMiddleware或Whitenoise WhiteNoiseMiddleware。 如果以前没有,则无法将CORS头添加到这些响应中。
如果你使用CORS_REPLACE_HTTPS_REFERER,它应该放在Django之前CsrfViewMiddleware
# 允许所有主机
CORS_ORIGIN_ALLOW_ALL = True
drf extensions
pip install drf-extensions
from rest_framework_extensions.cache.mixins import CacheResponseMixin
在继承类的第一位加入CacheResponseMixin
settings加入过期时间
REST_FRAMEWORK_EXTENSIONS = {
'DEFAULT_CACHE_RESPONSE_TIMEOUT':5
}
Social django app