books系列接口
查 单条和所有
def get(self, request, *args, **kwargs):
if kwargs.get('pk'):
book_list = models.Book.objects.all().filter(is_delete=False, pk=kwargs.get('pk'))
else:
book_list = models.Book.objects.all().filter(is_delete=False)
book_list_ser = BookModelSerializer(book_list, many=True)
return Response(data=book_list_ser.data)
增单条
增单条
def post(self, request, *args, **kwargs):
if isinstance(request.data,dict):
book_ser = BookModelSerializer(data=request.data)
book_ser.is_valid(raise_exception=True)
book_ser.save()
return Response(data=book_ser.data)
增所有
elif isinstance(request.data, list):
book_ser = BookModelSerializer(data=request.data, many=True)
book_ser.is_valid(raise_exception=True)
print(book_ser.data)
book_ser.save()
return Response(data=book_ser.data)
单条修改
def put(self, request, *args, **kwargs):
if kwargs.get('pk', None):
book_obj = models.Book.objects.filter(pk=kwargs.get('pk')).first()
book_ser = BookModelSerializer(instance=book_obj, data=request.data, partial=True)
book_ser.is_valid(raise_exception=True)
book_ser.save()
return Response(data=book_ser.data)
多条修改
else:
book_list = []
modify_data = []
for item in request.data:
pk = item.pop('id')
book = models.Book.objects.get(pk=pk)
book_list.append(book)
modify_data.append(item)
book_ser = BookModelSerializer(instance=book_list, data=modify_data, many=True)
book_ser.is_valid(raise_exception=True)
book_ser.save()
return Response(book_ser.data)
如果用来第二种方法 在序列化类里面加上这句话
class Meta:
list_serializer_class = BookListSerializer
在定义一个类
class BookListSerializer(serializers.ListSerializer):
def update(self, instance, validated_data):
return [
self.child.update(instance[i],attrs) for i,attrs in enumerate(validated_data)
]
批量删除
def delete(self, request, *args, **kwargs):
pk = kwargs.get('pk')
pks = []
if pk:
pks.append(pk)
else:
pks = request.data.get('pks')
ret = models.Book.objects.filter(pk__in=pks, is_delete=False).update(is_delete=True)
if ret:
return Response(data={'msg':'删除成功'})
else:
return Response(data={'msg': '没有要删除的数据'})
分页器的使用 (三种分页方式)
from rest_framework.generics import ListAPIView
from rest_framework.pagination import PageNumberPagination, LimitOffsetPagination, CursorPagination
'''
设置每页数据条数的配置在 类PageNumberPagination中
page_size: 每页显示条数
可以在settings.py里面进行设置 或者在这里写个类继承它然后设置 page_size属性值
'''
class MyPageNumberPagination(PageNumberPagination):
page_size = 3
page_query_param = 'aaa'
page_size_query_param = 'size'
max_page_size = 5
class MyPageNumberPagination(LimitOffsetPagination):
default_limit = 2
limit_query_param = 'limit'
offset_query_param = 'offset'
max_limit = 5
class MyPageNumberPagination(CursorPagination):
cursor_query_param = 'cursor'
page_size = 2
ordering = '-id'
class BookView(ListAPIView):
queryset = models.Book.objects.all().filter(is_delete=False)
serializer_class = BookModelSerializer
pagination_class = MyPageNumberPagination
如果使用APIView分页
from app01.throttling import MyThrottle
class BookView(APIView):
throttle_classes = [MyThrottle,]
def get(self, request, *args, **kwargs):
book_list = models.Book.objects.all()
page_cursor = MyPageNumberPagination()
book_list = page_cursor.paginate_queryset(book_list, request, view=self)
next_url = page_cursor.get_next_link()
pr_url = page_cursor.get_previous_link()
print(next_url)
print(pr_url)
book_ser = BookModelSerializer(book_list, many=True)
return Response(data=book_ser.data)
根据ip限制用户频率
创建一个throttling.py文件 在里面书写一下代码
from rest_framework.throttling import ScopedRateThrottle,SimpleRateThrottle
class MyThrottle(SimpleRateThrottle):
scope = 'luffy'
def get_cache_key(self, request, view):
return request.META.get('REMOTE_ADDR')
然后在settings.py中配置以下信息
REST_FRAMEWORK={
'DEFAULT_THROTTLE_RATES': {
'luffy': '5/m'
},
}
JWT的概念
jwt = Json Web token
# 原理
'''
1 jwt分三段式: 头 体 签名(head.payload.sgin)
2 头和体是可逆加密, 让服务器可以反解出user对象; 签名是不可逆加密, 保证整个token的安全性
3 头体签名三部分, 都是采用json格式的字符串,进行加密,可逆加密一般采用base64算法, 不可逆加密一般采用hash(md5)算法
4 头中的内容是基本信息: 公司信息 项目组信息 token采用的加密方式信息
{
"company": "公司信息”,
...
}
5 体中的内容是关键性信息: 用户主键, 用户名, 签发时客户端信息(设备号,地址),过期时间
{
“user_id": 1,
...
}
6 签名中的内容时安全信息: 头的加密结果 + 体的加密结果 + 服务器不对外公共的安全码 进行md5加密
{
"head": "头的加密字符串",
"payload": "体的加密字符串”,
"secret_key": "安全码"
'''
校验
'''
1 将token按 .拆分为三段字符串,第一段 头加密字符串 一般不需要做任何处理
2 第二段 体加密字符串, 要反解出用户主键, 通过主键从user表中就能得到登录用户, 过期时间和设备信息都是安全信息 ,确保token没过期, 且是同一设备
3 再用第一段 + 第二段 + 服务器安全码 不可逆md5加密, 与第三段 签名字符串 进行碰撞校验 , 通过后才能代表第二段校验得到的user对象就是合法的登录用户
'''
drf 项目的jwt认证开发流程(重点)
'''
1 用账号密码访问登录接口 , 登录接口逻辑中调用 签发token算法 ,得到token ,返回给客户端 ,客户端自己存到cookies中
2 校验token的算法应该写在认证类中(在认证类中调用), 全局配置给认证组件, 所有视图类请求, 都会进行认证校验, 所有请求带了token, 就会反解user对象, 在视图类中用request.user就能访问用户
注: 登录接口需要做 认证 + 权限 两个局部禁用
'''
第三方写好的 django-rest-framework-jwt
安装 pip install djangorestframework-jwt
新建一个项目, 继承AbstractUser表()
创建超级用户
简单使用
urls.py
from rest_framework_jwt.views import JSONWebTokenAPIView, obtain_jwt_token
urlpatterns = [
path('admin/', admin.site.urls),
path('login/', obtain_jwt_token),
]