drf表操作
一、面向对象二次封装Response
为方便多次调用Response方法,可将Response进行二次封装
response.py:
from rest_framework.response import Response class APIResponse(Response): # 格式化data def __init__(self, status=0, msg='ok', results=None, http_status=None, headers=None, exception=False, **kwargs): data = { # json的response基础有数据状态码和数据状态信息 'status': status, 'msg': msg } if results is not None: # 后台有数据,响应数据 data['results'] = results data.update(**kwargs) # 后台的一切自定义响应数据直接放到响应数据data中 super().__init__(data=data, status=http_status, headers=headers, exception=exception)
views.py:
class BookAPIView(APIview): def get(self, request, *args, **kwargs): pk = kwargs.get('pk') if pk: book_obj = models.Book.bojects.filter(pk=pk).first() if not boot_obj: # 以下内容被封装 # return Response({ # 'status': 1, # 'msg': 'pk error' # }, status=400) return APIResponse(1, 'pk error', http_static=400) book_data = serializers.BookModelSerializer(book_obj).data # return Response({ # 'status': 0, # 'msg': 'ok', # 'results': car_data # }) return APIResponse(results=book_data)
二、模型基表
Model类的内部配置Meta类要设置abstract=True,这样的Model类就是用来作为基表。
models.py:
class BookModel(models.Model): is_delete = models.BooleanField(default=False) create_time = models.DateField(auto_now_add=Ture) class Meta: # 基表必须设置abstract,基表就是给普通Model类继承使用的,设置了abstract就不会完成数据库迁移完成建表 abstract = Ture
三、多表ORM关联操作
3.1 表断关联
1、表之间没有外键关联,但是有外键逻辑关联(有充当外键的字段)
2、断关联后不会影响数据库查询效率,但是会极大提高数据库增删改效率(不影响增删改查操作)
3、断关联一定要通过逻辑保证表之间数据的安全
4、断关联
5、级联关系:
作者没了,详情也没:on_delete=models.CASCADE
出版社没了,书还是那个出版社出版:on_delete=models.DO_NOTHING
部门没了,员工没有部门(空不能):null=True, on_delete=models.SET_NULL
部门没了,员工进入默认部门(默认值):default=0, on_delete=models.SET_DEFAULT
models.py:
class Book(BaseModel): name = models.CharField(max_length=16) price = models.DecimalField(max_digits=5, decimal_places=2) publish = models.ForeignKey(to='Publish', related_name='books', db_constraint=False, on_delete=models.DO_NOTHING) # 多对多外键实际在关系表中,ORM默认关系表中两个外键都是级联 # ManyToManyField字段不提供设置on_delete,如果想设置关系表级联,只能手动定义关系表 author = models.ManyToManyField(to='Author', related_name='books', db_constraint=False) # 自定义连表深度,不需要反序列化,因为自定义插拔属性不参与反序列化 @property def publish_name(self): return self.publish.name @property def author_list(self): temp_author_list = [] for author in self.authors.all(): temp_author_list.append({ 'name': author.name, 'sex': author.get_sex_display(), 'mobile': author.detail.mobile }) return temp_author_list class Publish(baseModel): name = models.CharField(max_length=16) sex = models.IntegerField(choices=[(0,'男'),(1,'女')], default=0) class AuthorDetail(BaseModel): mobile = models.CharField(max_length=11) # 有作者可以没有详情,删除作者,详情一定会被级联删除 # 外键字段为正向查询字段,related_name是反向查询字段 autor = models.OneToOneField(to='Author', related_name='detail', db_constraint=False, on_delete=models.CASCADE)
3.2 ORM外键设计
1、一对多:外键放在多的一方
2、多对多:外键放在常用的一方
3、一对一:外键放在不常用的一方
4、外键字段为正向查询字段,related_name是反向查询字段
四、连表序列化
serializers.py:
class BookListSerializer(serializers.ListSerializer): # 1、create方法父级ListSerializer已经提供了 # 2、父级ListSerializer没有通过update方法的实现体,需要重写 def update(self, instance, validated_data): return [ self.child.update(instance[i],attrs) for i,attrs in enumerate(validated_data) ] class BookModelSerializer(serializers.ListSerializer) # 通过BookModelSerializer.Meta.list_serializer_class来访问绑定的ListSerializer class Meta: list_serializer_class = BookListSerializer model = moldes.Book # 序列化反序列化整合 fields = ('name', 'price', 'publish_name', 'author_list', 'publish', 'authors') extra_kwargs = { 'publish': { 'wite_only': Ture }, 'authors': { 'wite_only': Ture } } class PublishModelSerializer(serializers.ModelSerializer): # 子序列化都是提供给外键(正向方向)完成深度查询的,外键数据是唯一:many=False;不唯一:many=True # 注:只能参与序列化,且反序列化不能写(反序列化外键字段会抛异常) books = BookModelSerializer(many=True) class Meta: model = models.Publish field = ('name', 'address', 'books')
五、单查群查序列化
views.py:
class BookAPIView(APIView): def get(self, request, *args, **kwargs): pk = kwargs.get('pk') if pk: book_obj = models.Book.objects.filter(pk=pk, is_delete=False).first() if not book_obj: return APIResponse(1, 'pk error', http_status=400) book_data = serializers.BookModelSerializer(book_obj).data return APIResponse(results=book_data) book_query = models.Book.objects.filter(is_delete=False).all() return APIResponse(0, 'ok', data=serializers.BookModelSerializer(book_query, many=True).data)
六、单删群删接口
def delete(self, request, *args, **kwargs): pk = kwargs.get('pk') if pk: pks = [pk] else: pks = request.data.get('pks') if not pks: return APIResponse(1, 'delete error', http_status=400) rows = models.Book.objects.filter(is_delete=False, pk__in=pks).update(is_delete=Ture) if rows: return APIResponse(0,'delete ok') return APIResponse(1, 'delete failed')
七、单增群增接口
def post(self, request, *args, **kwargs): request_data = request.data # 单增 if isinstance(request_data, dict) book_ser = serializers.BookModelSerializer(data=request_data) if book_ser.is_valid(): book_obj = book_ser.save() return APIResponse(results=serializers.BookModelsSerializer(book_obj).data) return APIResponse(1, msg=book_ser.errors) elif isinstance(request_data, list)and len(request_data) != 0: #群增 book_ser = serializers.BookModelSerializer(data=request_data, many=Ture) book_ser.is_valid(raise_exception=True) book_obj_list = book_ser.save() return APIResponse(results=serializers.BookModelSerializer(book_obj_list, many=True).data) else: return APIResponse(1, 'data error', http_status=400)
八、单整体改、群整体改
def put(self, request, *args, **kwargs): pk = kwargs.get('pk') request_data = request.data if pk: # 单改 try: book_obj = models.Book.objects.get(pk=pk) except: return APIResponse(1, 'pk error') # 修改和新增,都需要通过数据,数据依旧给data,修改与新增不同点,instance要被赋值为被修改对象 book_ser = serializers.BookModelSerializer(instance=book_obj, data=request_data) book_ser.is_valid(raise_exception=True) book_obj = book_ser.save() return APIResponse(results=serializers.BookModelSerializer(book_obj).data) else: # 群改 if not isintance(request_data, list) or len(request_data) == 0: return APIResponse(1, 'data error', http_status=400) obj_list = [] data_list = [] for dic in request_data: try: pk = dic.pop('pk') try: obj = models.Book.objects.get(pk=pk, is_delete=False) obj_list.append(obj) data_list.append(dic) except: pass except: return APIResponse(1, 'data error', http_status=400) book_ser = serializers.BookModelSerializer(instance=obj_list, data=data_list, many=True) book_ser.is_valid(raise_exception=True) book_obj_list = book_ser.save() return APIResponse(results=serializers.BookModelSerializer(book_obj_list, many=True).data)
九、单局部与群局部修改
def patch(self, request, *args, **kwargs): pk = kwargs.get('pk') request_data = request.data if pk: try: book_obj = models.Book.objects.get(pk=pk) except: return APIResponse(1, 'pk error') book_ser = serializers.BookModelSerializer(instance=book_obj, data=request_data, partial=Ture) book_ser.is_valid(raise_exception=Ture) book_obj = book_ser.save() return APIResponse(results=serializers.BookModelSerializer(book_obj).data) else: # 群增 if not isinstance(request_data, list) or len(request_data) == 0: return APIResponse(1, 'data error', http_status=400) # 注:一定不要在循环体中对循环对象进行增删(影响对象长度)的操作 obj_list = [] data_list = [] for dic in request_data: # request_data可能是list,单内部不一定是dict try: pk = dic.pop('pk') try: obj = models.Book.objects.get(pk=pk, is_delete=False) obj_list.append(obj) data_list.append(dic) except: pass except: return APIResponse(1, 'data error', http_status=400) book_ser = serializers.BookModelSerializer(instance=obj_list, data=data_list, many=True, partial=True) book_ser.is_valid(raise_exception=True) book_obj_list = book_ser.save() return APIResponse(results=serializers.BookModelSerializer(book_obj_list, many=True).data)