伏雨朝寒悉不胜,那能还傍杏花行。去年高摘斗轻盈。漫惹炉烟双袖紫,空将酒晕一衫青。人间何处问多情。 ———— 纳兰容若
常规开发:前后端不分离(后端直接用render、HttpResponse给前端)
Django里的FBV、CBV:
def users(request): list = ['a','b','c'] return HttpResponse(json.dumps(list))
->urls.py urlpatterns = [url(r'^students/'),views.StudentsView.as_view(),] ->views.py from django.views import View class StudentsView(View): def get(self,request,*args,**kwargs): return HttpResponst('GET') def post(self,request,*args,**kwargs): return HttpResponst('POST') def put(self,request,*args,**kwargs): return HttpResponst('PUT') def delete(self,request,*args,**kwargs): return HttpResponst('DELETE') def get(self,request,*args,**kwargs): return HttpResponst('GET') def get(self,request,*args,**kwargs): return HttpResponst('GET')
当访问/students路径,自动识别请求模式(自动分发),不同method显示不同响应。
列表生成式:
class Foo: pass class Bar: pass v = [] for i in [Foo,Bar]: object = i() v.append(object)
v = [i() for i in [Foo,Bar]]
第一种写法等同于第二种写法,第二种写法是第一种写法的简化版,此时v就是对象列表。
- 面向对象
……
面试题:
1.Django中间件
- process_request
- process_view
- process_response
- process_exception
process_render_template
2.中间件用途
- 权限
- 用户登录
csrfToken的实现?
FBV:
from django.views.decorators.csrf import csrf_exempt,csrf_protect
在process_view方法里实现,检查视图是否被@csrf_exempt装饰,如果有,则免除csrf认证,如果全站禁止csrf认证,需要做局部认证,可在函数前用@csrf_protect装饰
在请求体或cookie中获取token做校验CBV:
from django.utils.decorators import method_decorator from django.views.decorators.csrf import csrf_exempt,csrf_protect # 在class之前加装饰器: @method_decorator(csrf_exempt,name='dispatch')
restful 规范
写一个URL,在后台根据method的不同区分增删改查(获取、创建、更新、删除)
FBV:
如: urlpatterns = [url('order/',views.order_view)]
后端: def order_view(request):
if request.method == "GET\POST\PUT\DELETE":
return HttpResponse("……")CBV:
如: urlpatterns = [url('order/',views.OrderView.as_view())]
后端: class OrderView(View):
def get、post、put、delete(self,request,args,*kwargs):
return HttpResponse("……")
Django restful framework
pip3 install djangorestframework
认证:
如何控制用户使用接口?
- 随机字符串(token)
有些api需要用户登录才能使用,有些不需登录即可使用。
- 创建两张表,一张存user登陆信息,另一张存用户token。
- 用户登陆,创建token并保存到数据库
- 认证流程原理:
写认证的时候:
- 创建一个类:
_from _rest_framework.authentication _import _BaseAuthentication
继承BaseAuthentication类,实现两个方法,重要的是实现authenticate方法。authenticate_header方法可以直接pass
authenticate方法有三种返回值:
- None,表示让下一个认证来执行认证。
- _from _rest_framework _import _exceptions
raise exceptions.AuthenticationFailed('认证失败'),抛出异常。
3. (元素1,元素2)。元素1赋值给request.user,元素2赋值给request.auth。
全局/局部认证。
- 局部:在views视图里写局部字段,只对单个class视图进行单个认证
全局:使用setting配置文件:(写的是认证类的路径!!!)
- REST_FRAMEWORK = {
"DEFAULT_AUTHENTICATION_CLASSES":['api.utils.auth.FirstAuthtication','api.utils.auth.Authtication',],
'UNAUTHENTICATED_USER':_None_,
'UNAUTHENTICATED_TOKEN':_None_,
- REST_FRAMEWORK = {
}
权限:
from rest_framework.permissions import BasePermission,继承BasePermission类,实现has_permission(self,request,view)方法。
- 返回值有两种:False和True。
- 如果返回False,要写message=‘自定义信息’。
- 全局/局部在setting里设置。DEFAULT_PERMISSION_CLASSES
访问频率控制:
- 继承BaseThrottle,实现_allow_request_以及_wait_
或
版本:
版本可通过URL的GET形式传参。
# http://127.0.0.1:8000/api/user/?v=2 class ParamVersion(object): def determine_version(self,request,*args,**kwargs): v = request.query_params.get('v') return v class UsersView(APIView): versioning_class = ParamVersion def get(self,request,*args,**kwargs): print(request.version) return HttpResponse('user list')
通过URL中的正则表达式传递。
# 应用的urls.py中: urlpatterns = [ re_path(r'^(?P<version>[v1|v2]+)/user/$',views.UsersView.as_view()) ] # settings.py中 REST_FRAMEWORK = {"DEFAULT_VERSIONING_CLASS":"rest_framework.versioning.URLPathVersioning",}
解析器:
全局配置
# settings.py中
REST_FRAMEWORK = {
"DEFAULT_PARSER_CLASSES":['rest_framework.parsers.JSONParser'],
}
# 视图中可通过request.data获取数据
局部配置
可在视图函数局部加入parser_classes = [FileUploadParser,],然后用request.FILES获取相关数据即可。
序列化
写一个类,可以继承serializers.Serializer或serializers.ModelSerializer。
class RolesSerializer(serializers.Serializer):
id = serializers.IntegerField()
title = serializers.CharField()
# 或
class UserInfoSerializer(serializers.ModelSerializer):
class Meta:
model = models.UserInfo
fields = '__all__'
# fields = ['id','username','password']
对于自定义的字段:
- xxx = serializers.CharField(source='xxxx.xxxx')
或
xxx = serializers.SerializerMethodField(),如下:
class UserInfoSerializer(serializers.ModelSerializer): # 多对多的做法 rls = serializers.SerializerMethodField() def get_rls(self, row): row_obj_list = row.roles.all() ret = [] for i in row_obj_list: ret.append({"id": i.id, "title": i.title}) return ret class Meta: model = models.UserInfo fields = ['id','username','password','xxx','rls',]
深度控制
class UserInfoSerializer(serializers.ModelSerializer): class Meta: model = models.UserInfo fields = ['id','username','password','group','roles'] depth = 1 #默认0层,深度控制建议1~10之间
生成链接
# urls.py中 urlpatterns = [re_path(r'^(?P<version>[v1|v2]+)/group/(?P<pk>\d+)$',views.GroupView.as_view(),name='gp'),] # views.py中 class UserInfoSerializer(serializers.ModelSerializer): group = serializers.HyperlinkedIdentityField('gp',lookup_field='group_id',lookup_url_kwarg='pk') class Meta: model = models.UserInfo fields = ['id','username','password','group','roles'] depth = 0 #默认0层,深度控制建议1~10之间 class UserInfoView(APIView): def get(self,request, *args, **kwargs): users = models.UserInfo.objects.all() ser = UserInfoSerializer(instance=users,many=True,context={'request': request}) ret = json.dumps(ser.data, ensure_ascii=False) return HttpResponse(ret)
请求数据校验(接收数据的校验)
class UserGroupSerializer(serializers.Serializer): title = serializers.CharField(error_messages={'required':'title不能空'}) class UserGroupView(APIView): def post(self, request, *args, **kwargs): ser = UserGroupSerializer(data=request.data) if ser.is_valid(): print(ser.validated_data['title']) else: print(ser.errors) return HttpResponse('提交de数据')
自定义验证规则
分页
普通分页
# views.py中
from api.utils.serializers.pager import PagerSerializers
from rest_framework.response import Response
from rest_framework.pagination import PageNumberPagination
# 自定义分页
class MyPageNumberPagination(PageNumberPagination):
page_size = 2
# 控制一页显示个数的URL字段
page_size_query_param = 'size'
# 控制size最大能拿多少个数据
max_page_size = 4
class Pager1View(APIView):
def get(self, request, *args, **kwargs):
# 获取所有数据
roles = models.Role.objects.all()
# ret = json.dumps(ser.data)
# 创建分页对象
# pg = PageNumberPagination()
# 使用自定义创建的更多功能的分页对象
pg = MyPageNumberPagination()
# 数据库中获取分页数据
pager_roles = pg.paginate_queryset(roles,request,self)
# 对数据序列化
ser = PagerSerializers(instance=pager_roles,many=True)
# 传分页后的正常数据信息
# return Response(ser.data)
# 传分页后的更多信息
return pg.get_paginated_response(ser.data)
# settings.py中
REST_FRAMEWORK = {"PAGE_SIZE":2}
从第n个数据向后取
from api.utils.serializers.pager import PagerSerializers
from rest_framework.pagination import LimitOffsetPagination
class MyPageNumberPagination(LimitOffsetPagination):
default_limit = 2
limit_query_param = 'limit'
offset_query_param = 'offset'
max_limit = 3
class Pager1View(APIView):
def get(self, request, *args, **kwargs):
# 获取所有数据
roles = models.Role.objects.all()
# 使用自定义创建的更多功能的分页对象
pg = LimitOffsetPagination()
# 数据库中获取分页数据
pager_roles = pg.paginate_queryset(roles,request,self)
# 对数据序列化
ser = PagerSerializers(instance=pager_roles,many=True)
# 传更多信息
return pg.get_paginated_response(ser.data)
# url中:http://127.0.0.1:8000/api/v1/pager1/?limit=2&offset=4
加密分页
from api.utils.serializers.pager import PagerSerializers
from rest_framework.pagination import CursorPagination
class MyPageNumberPagination(CursorPagination):
cursor_query_param = 'cursor'
page_size = 3
ordering = 'id'
page_size_query_param = 2
max_page_size = 5
class Pager1View(APIView):
def get(self, request, *args, **kwargs):
# 获取所有数据
roles = models.Role.objects.all()
# 创建分页对象
# pg = PageNumberPagination()
# 使用自定义创建的更多功能的分页对象
pg = MyPageNumberPagination()
# 数据库中获取分页数据
pager_roles = pg.paginate_queryset(roles,request,self)
# 对数据序列化
ser = PagerSerializers(instance=pager_roles,many=True)
# 传更多信息
return pg.get_paginated_response(ser.data)
高级视图操作(直接实现四操作)
# views.py中
# 直接实现增删改查
from api.utils.serializers.pager import PagerSerializers
from rest_framework.viewsets import ModelViewSet
class View2View(ModelViewSet):
queryset = models.Role.objects.all()
serializer_class = PagerSerializers
pagination_class = MyPageNumberPagination
# urls.py中,一个URL要写两个路由
urlpatterns = [re_path(r'^(?P<version>[v1|v2]+)/view2/$',views.View2View.as_view({'get':'list','post':'create'})),
re_path(r'^(?P<version>[v1|v2]+)/view2/(?P<pk>\d+)/$',views.View2View.as_view({'get':'retrieve','delete':'destroy','put':'update','patch':'partial_update'})),]
自动生成路由(直接覆盖四操作的路由系统)
from django.urls import path, include, re_path
from api import views
from rest_framework import routers
router = routers.DefaultRouter()
router.register(r'view2',views.View2View)
urlpatterns = [re_path(r'^(?P<version>[v1|v2]+)/',include(router.urls))]
渲染器
# settings.py中
REST_FRAMEWORK = {"DEFAULT_RENDERER_CLASSES":['rest_framework.renderers.JSONRenderer']}