Day 74 Ten interface / depth (with table) query

DRF serialization

Depth (with table) query

Subsequence of

  1. It can only be used in serialization

  2. Field name must be the foreign key name (Forward Reverse)

    With respect to the custom sequence Outsider key fields, custom serialization fields are not involved in anti-serialized, and the child must be serialized foreign key name, so it is not out of the library

  3. Foreign key is associated with a number of data, you need to clear many = True

  4. Is a one-way operation, because as a sequence of the class must be written at the top, it can not produce the sub-sequence of the reverse direction

depth

,, automatic depth value representing the depth of times, but the depth is the foreign key __all__ is employed, show all fields (not recommended)

@property

Plug-in, the name is not the same as the foreign key name

Second package Response

"""
return MyResponse(status=1, msg='error', results=[], token='a.b.c', http_status=400, exception=True)

return Response(
    data={
        'status': 1,
        'msg': 'error',
        'results': [],
        token: 'a.b.c'
    },
    status=400,
    exception=True
)

return APIResponse(1, 'error', results=[], token='a.b.c', http_status=400, exception=True)
"""
from rest_framework.response import Response
class APIResponse(Response):
    def __init__(self, status=0, msg='ok', results=None, http_status=None,
                 headers=None, exception=False, content_type=None, **kwargs):
        # 将status、msg、results、kwargs格式化成data
        data = {
            'status': status,
            'msg': msg,
        }
        # results只要不为空都是数据:False、0、'' 都是数据 => 条件不能写if results
        if results is not None:
            data['results'] = results
        # 将kwargs中额外的k-v数据添加到data中
        data.update(**kwargs)

        super().__init__(data=data, status=http_status, headers=headers, exception=exception, content_type=content_type)
# 一定要在settings文件中将异常模块配置自己的异常处理函数
from rest_framework.views import exception_handler as drf_exception_handler
from rest_framework.response import Response
from rest_framework import status
def exception_handler(exc, context):
    response = drf_exception_handler(exc, context)
    detail = '%s - %s - %s' % (context.get('view'), context.get('request').method, exc)
    if not response:  # 服务端错误
        response = Response({'detail': detail}, status=status.HTTP_500_INTERNAL_SERVER_ERROR)
    else:
        response.data = {'detail': detail}

    # 核心:要将response.data.get('detail')信息记录到日志文件
    # logger.waring(response.data.get('detail'))

    import sys
    sys.stderr.write('异常:%s\n' % response.data.get('detail'))

    return response

Ten Interface

Danchaquncha

def get(self, request, *args, **kwargs):
    pk = kwargs.get('pk')
    if pk:
        book_obj = models.Book.objects.filter(is_delete=False, pk=pk).first()
        book_ser = serializers.BookModelSerializer(book_obj)
    else:
        book_query = models.Book.objects.filter(is_delete=False).all()
        book_ser = serializers.BookModelSerializer(book_query, many=True)
    return APIResponse(results=book_ser.data)
        # return Response(data=book_ser.data)

Danshanqunshan

def delete(self, request, *args, **kwargs):
    """
    单删:接口:/books/(pk)/   数据:空
    群删:接口:/books/   数据:[pk1, ..., pkn]
    逻辑:修改is_delete字段,修改成功代表删除成功,修改失败代表删除失败
    """
    pk = kwargs.get('pk')
    if pk:
        pks = [pk]  # 将单删格式化成群删一条
    else:
        pks = request.data  # 群删
    try:  # 数据如果有误,数据库执行会出错
        rows = models.Book.objects.filter(is_delete=False, pk__in=pks).update(is_delete=True)
    except:
        return APIResponse(1, '数据有误')
    if rows:
        return APIResponse(0, '删除成功')
    return APIResponse(1, '删除失败')

Tenzin group increased

def post(self, request, *args, **kwargs):
    """
    单增:接口:/books/   数据:{...}
    群增:接口:/books/   数据:[{...}, ..., {...}]
    逻辑:将数据给系列化类处理,数据的类型关系到 many 属性是否为True, 单增为字典类型,群增为列表类型
    """
    if isinstance(request.data, dict):
        many = False
    elif isinstance(request.data, list):
        many = True
    else:
        return Response(data={'detail': '数据有误'}, status=400)
    
    book_ser = serializers.BookModelSerializer(data=request.data, many=many)
    book_ser.is_valid(raise_exception=True)  # 如果校验不通过,直接报异常
    book_obj_or_list = book_ser.save()
    return APIResponse(results=serializers.BookModelSerializer(book_obj_or_list, many=many).data)

Single change the overall population change

def put(self, request, *args, **kwargs):
    """
    单改:接口:/books/(pk)/   数据:{...}
    群增:接口:/books/   数据:[{pk, ...}, ..., {pk, ...}]
    逻辑:将数据给系列化类处理,数据的类型关系到 many 属性是否为True
    """
    pk = kwargs.get('pk')
    if pk:  # 单改
        try:
            # 与增的区别在于,需要明确被修改的对象,交给序列化类
            book_instance = models.Book.objects.get(is_delete=False, pk=pk)
        except:
            return Response({'detail': 'pk error'}, status=400)

        book_ser = serializers.BookModelSerializer(instance=book_instance, data=request.data)
        book_ser.is_valid(raise_exception=True)
        book_obj = book_ser.save()
        return APIResponse(results=serializers.BookModelSerializer(book_obj).data)
    else:  # 群改
        # 分析(重点):
        # 1)数据是列表套字典,每个字典必须带pk,就是指定要修改的对象,如果有一条没带pk,整个数据有误
        # 2)如果pk对应的对象已被删除,或是对应的对象不存在,可以认为整个数据有误(建议),可以认为将这些错误数据抛出即可
        request_data = request.data
        try:
            pks = []
            for dic in request_data:
                pk = dic.pop('pk')  # 解决分析1,没有pk pop方法就会抛异常
                pks.append(pk)

            book_query = models.Book.objects.filter(is_delete=False, pk__in=pks).all()
            if len(pks) != len(book_query):
                raise Exception('pk对应的数据不存在')
        except Exception as e:
            return Response({'detail': '%s' % e}, status=400)

        book_ser = serializers.BookModelSerializer(instance=book_query, data=request_data, many=True)
        book_ser.is_valid(raise_exception=True)
        book_list = book_ser.save()
        return APIResponse(results=serializers.BookModelSerializer(book_list, many=True).data)

Local population of a single change change

def patch(self, request, *args, **kwargs):
    pk = kwargs.get('pk')
    if pk:  # 单改
        try:
            book_instance = models.Book.objects.get(is_delete=False, pk=pk)
        except:
            return Response({'detail': 'pk error'}, status=400)
        # 设置partial=True的序列化类,参与反序列化的字段,都会置为选填字段
        # 1)提供了值得字段发生修改。
        # 2)没有提供的字段采用被修改对象原来的值

        # 设置context的值,目的:在序列化完成自定义校验(局部与全局钩子)时,可能需要视图类中的变量,如请求对象request
        # 可以通过context将其传入,在序列化校验方法中,self.context就能拿到传入的视图类中的变量
        book_ser = serializers.BookModelSerializer(instance=book_instance, data=request.data, partial=True, context={'request': request})
        book_ser.is_valid(raise_exception=True)
        book_obj = book_ser.save()
        return APIResponse(results=serializers.BookModelSerializer(book_obj).data)
    else:  # 群改
        request_data = request.data
        try:
            pks = []
            for dic in request_data:
                pk = dic.pop('pk')
                pks.append(pk)
            book_query = models.Book.objects.filter(is_delete=False, pk__in=pks).all()
            if len(pks) != len(book_query):
                raise Exception('pk对应的数据不存在')
        except Exception as e:
            return Response({'detail': '%s' % e}, status=400)

        book_ser = serializers.BookModelSerializer(instance=book_query, data=request_data, many=True, partial=True)
        book_ser.is_valid(raise_exception=True)
        book_list = book_ser.save()
        return APIResponse(results=serializers.BookModelSerializer(book_list, many=True).data)

Guess you like

Origin www.cnblogs.com/2222bai/p/12113009.html