Book多增多删接口、分页器、IP限制
Book多增多删接口、分页器、IP限制
多增多删接口
#views.py
from rest_framework.views import APIView
from app01.models import Book
from app01.ser import BookModelSerializer
from app01.utils.response import APIResponse
class BookAPIView(APIView):
#查单个、查所有
def get(self,request,*args,**kwargs):
pk = kwargs.get('pk')
if pk:
print('少')
book = Book.objects.filter(pk=pk,is_delete=False).first()
book_ser = BookModelSerializer(book)
return APIResponse(data=book_ser.data)
else:
print('多')
book_list = Book.objects.filter(is_delete=False).all()
book_list_ser = BookModelSerializer(book_list,many=True)
return APIResponse(data=book_list_ser.data)
def post(self,request,*args,**kwargs):
#规定前端格式、字典是单个数据,列表是多个数据
#isinstance判断request.data是不是字典,是就单增
if isinstance(request.data,dict):
print('少')
book_ser = BookModelSerializer(data=request.data)
#数据效验失败抛出异常,不需要判断是否合法了
book_ser.is_valid(raise_exception=True)
book_ser.save()
return APIResponse(data=book_ser.data)
# isinstance判断request.data是不是列表,是就群增
elif isinstance(request.data,list):
print('多')
#此时需要用BookListSerializer来群增
book_ser = BookModelSerializer(data=request.data,many=True)
book_ser.is_valid(raise_exception=True)
book_ser.save()
return APIResponse(data=book_ser.data)
def delete(self,request,*args,**kwargs):
pk = kwargs.get('pk')
pks = []
if pk:
pks.append(pk)
else:
pks = request.data.get('pks')
print(pks)
#pk__in就是在pks一个一个循环
ret = Book.objects.filter(pk__in=pks,is_delete=False).update(is_delete=True)
if ret:
print(ret)
return APIResponse(msg='删除成功%s条数据'%(ret))
else:
return APIResponse(msg='没有需要删除的数据')
def put(self,requesst,*args,**kwargs):
if kwargs.get('pk'):
#改单个
print('少')
book = Book.objects.filter(pk=kwargs.get('pk')).first()
#partial=True表示改局部的,相当于其他字段等于required=False
book_ser = BookModelSerializer(instance=book,data=requesst.data,partial=True)
# raise_exception=True报错建议自定义异常处理,会被捕获
book_ser.is_valid(raise_exception=True)
book_ser.save()
return APIResponse(data=book_ser.data)
else:
print('多')
#改多个,要求格式列表套字典[{id:1,name:xx,price:xx},{id:1,name:xx,price:xx}]
book_list = []
#modify_data修改的数据
modify_data = []
for item in requesst.data:
print(item)
pk = item.pop('id')
book = Book.objects.get(pk=pk)
book_list.append(book)
modify_data.append(item)
# print(modify_data)
#第一方案,for循环一个个改
# for i,put_data in enumerate(modify_data):
# book_ser = BookModelSerializer(instance=book_list[i],data=put_data)
# book_ser.is_valid(raise_exception=True)
# book_ser.save()
# return APIResponse(data=book_ser.data)
#第二种方案,重写ListSerializer的update方法
print(book_list,modify_data)
book_ser = BookModelSerializer(instance=book_list,data=modify_data,many=True,partial=True)
book_ser.is_valid(raise_exception=True)
book_ser.save()
return APIResponse({'msg':'修改成功'})
#modles.py
from django.db import models
class BaseModel(models.Model):
is_delete = models.BooleanField(default=False)
create_time = models.DateTimeField(auto_now_add=True)
last_update_time = models.DateTimeField(auto_now=True)
class Meta:
abstract = True#抽象表,不在数据库创建
class Book(BaseModel):
name = models.CharField(max_length=32)
price = models.DecimalField(max_digits=5,decimal_places=2)
authors = models.ManyToManyField(to='Author',db_constraint=False)
publishs = models.ManyToManyField(to='Publish',db_constraint=False)
def __str__(self):
return self.name
@property
def author_list(self):
author_list2 = self.authors.all()
return [{'name':author.name,'sex':author.get_sex_display()}for author in author_list2]
@property
def publish_list(self):
publish_list2 = self.publishs.all()
return [{'name':pubisj.name,'addr':pubisj.addr}for pubisj in publish_list2]
class Author(BaseModel):
name = models.CharField(max_length=32)
sex = models.IntegerField(choices=((1,'男'),(2,'女')))
authordetail = models.OneToOneField(to='AuthorDetail',db_constraint=False,on_delete=models.CASCADE)
class AuthorDetail(BaseModel):
age = models.IntegerField()
mobile = models.CharField(max_length=11)
class Publish(BaseModel):
name = models.CharField(max_length=32)
addr = models.CharField(max_length=32)
def __str__(self):
return self.name
#ser.py
from rest_framework import serializers
from app01.models import Book
class BookListSerializer(serializers.ListSerializer):
def update(self, instance, validated_data):
print(instance,validated_data)
return [self.child.update(instance[i],attrs) for i, attrs in enumerate(validated_data)]
class BookModelSerializer(serializers.ModelSerializer):
name = serializers.CharField()
class Meta:
list_serializer_class = BookListSerializer
model=Book
fields = ('id','name','price','authors','author_list','publishs','publish_list')
extra_kwargs = {
# 'id':{'read_only':True},
'author_list':{'read_only':True},
'authors':{'write_only':True},
'publishs':{'write_only':True},
'publish_list':{'read_only':True}
}
admin.py注册下,方便admin页面添加数据
from app01 import models
admin.site.register(models.Book)
admin.site.register(models.Author)
admin.site.register(models.AuthorDetail)
admin.site.register(models.Publish)
自定义的reponse对象
from rest_framework.response import Response
class APIResponse(Response):
def __init__(self, code=100, msg='成功', data=None, status=None, headerrs=None, **kwargs):
dic = {'code': code, 'msg': msg}
if data:
dic = {'code': code, 'msg': msg, 'data': data}
dic.update(kwargs)
super().__init__(data=dic, status=status, headers=headerrs)
只有上下页的分页器
#查所有才需要分页
#基于APIView分页
from rest_framework.views import APIView
from app01.utils.throttling import MyCursorPagination
from app01.models import Book
from app01.ser import BookModelSerializer
from app01.utils.response import APIResponse
class BookTestAPIview(APIView):
def get(self,request,*args,**kwargs):
book_list = Book.objects.all()
#实例化得到分页器对象
page_cursor = MyCursorPagination()
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,pr_url)
book_ser = BookModelSerializer(book_list,many=True)
return APIResponse(data=book_ser.data)
throttling.py
from rest_framework.pagination import CursorPagination
class MyCursorPagination(CursorPagination):
cursor_query_param = 'cursor' # 每一页查询的key
page_size = 2 #每页显示的条数
ordering = 'id' #排序字段
IP进行频率限制
#写一个类,继承SimpleRateThrottle,重写get_cache_key
#ipthrottling.py
#IP频率限制
from rest_framework.throttling import SimpleRateThrottle
class MyThrottle(SimpleRateThrottle):
scope = 'luffy'
def get_cache_key(self, request, view):
return request.META.get('REMOTE_ADDR')
#全局配置
#settins.py
REST_FRAMEWORK={
'DEFAULT_THROTTLE_CLASSES': (
'app01.utils.ipthrotting.MyThrottle',
),
'DEFAULT_THROTTLE_RATES': {
'luffy': '3/m' # key要跟类中的scop对应
},
}
#views.py
from rest_framework.views import APIView
from app01.utils.response import APIResponse
class TestAPIView(APIView):
def get(self,request,*args,**kwargs):
return APIResponse()#这是自定义的Response对象,可以用from rest_framework.response import Response的
#局部使用
#settings.py
REST_FRAMEWORK={
'DEFAULT_THROTTLE_RATES': {
'luffy': '3/m' # key要跟类中的scop对应},}
#views.py
from rest_framework.views import APIView
from app01.utils.response import APIResponse
from app01.utils.ipthrotting import MyThrottle
class TestAPIView(APIView):
throttle_classes = [MyThrottle]
def get(self,request,*args,**kwargs):
return APIResponse()#这是自定义的Response对象,可以用from rest_framework.response import Response的