from rest_framework import mixins from rest_framework import serializers from rest_framework import status from rest_framework.relations import ManyRelatedField, RelatedField, PrimaryKeyRelatedField from rest_framework.request import Request from .response import SuccessResponse class CreateModelMixin(mixins.CreateModelMixin): """ 继承、增强DRF的CreateModelMixin, 标准化其返回值 """ create_serializer_class = None def create(self, request: Request, *args, **kwargs): serializer = self.get_serializer(data=request.data) serializer.is_valid(raise_exception=True) self.perform_create(serializer) if hasattr(self, 'handle_logging'): self.handle_logging(request, instance=serializer.instance, *args, **kwargs) headers = self.get_success_headers(serializer.data) return SuccessResponse(serializer.data, status=status.HTTP_201_CREATED, headers=headers) def perform_create(self, serializer): super().perform_create(serializer) class ListModelMixin(mixins.ListModelMixin): """ 继承、增强DRF的CreateModelMixin, 标准化其返回值 """ list_serializer_class = None def list(self, request: Request, *args, **kwargs): queryset = self.filter_queryset(self.get_queryset()) page = self.paginate_queryset(queryset) if hasattr(self, 'handle_logging'): self.handle_logging(request, *args, **kwargs) if page is not None: if getattr(self, 'values_queryset', None): return self.get_paginated_response(page) serializer = self.get_serializer(page, many=True) return self.get_paginated_response(serializer.data) if getattr(self, 'values_queryset', None): return SuccessResponse(page) serializer = self.get_serializer(queryset, many=True) return SuccessResponse(serializer.data) class RetrieveModelMixin(mixins.RetrieveModelMixin): """ 继承、增强DRF的CreateModelMixin, 标准化其返回值 """ retrieve_serializer_class = None def retrieve(self, request: Request, *args, **kwargs): instance = self.get_object() serializer = self.get_serializer(instance) if hasattr(self, 'handle_logging'): self.handle_logging(request, instance=instance, *args, **kwargs) return SuccessResponse(serializer.data) class UpdateModelMixin(mixins.UpdateModelMixin): """ 继承、增强DRF的CreateModelMixin, 标准化其返回值 """ update_serializer_class = None def update(self, request: Request, *args, **kwargs): partial = kwargs.pop('partial', False) instance = self.get_object() serializer = self.get_serializer(instance, data=request.data, partial=partial) serializer.is_valid(raise_exception=True) self.perform_update(serializer) if getattr(instance, '_prefetched_objects_cache', None): instance._prefetched_objects_cache = {} if hasattr(self, 'handle_logging'): self.handle_logging(request, instance=instance, *args, **kwargs) return SuccessResponse(serializer.data) def partial_update(self, request, *args, **kwargs): kwargs['partial'] = True return self.update(request, *args, **kwargs) class DestroyModelMixin(mixins.DestroyModelMixin): """ 继承、增强DRF的CreateModelMixin, 标准化其返回值 """ destroy_serializer_class = None def destroy(self, request: Request, *args, **kwargs): instance = self.get_object() self.perform_destroy(instance) if hasattr(self, 'handle_logging'): self.handle_logging(request, instance=instance, *args, **kwargs) return SuccessResponse(status=status.HTTP_204_NO_CONTENT) def perform_destroy(self, instance): instance.delete() class TableSerializerMixin: table_option = None extra_columns = [] FIELD_TYPE_MAP = { 'AutoField': { 'type': 'input', 'addDisabled': True, }, 'CharField': { 'type': 'input', "maxlength": 255 }, 'PasswordField': { 'type': 'input', 'maxlength': 255 }, 'URLField': { 'type': 'input', }, 'UUIDField': { 'type': 'input', 'minlength': 32, 'maxlength': 32, }, 'UUID8Field': { 'type': 'input', 'minlength': 8, 'maxlength': 8, }, 'UUID16Field': { 'type': 'input', 'minlength': 16, 'maxlength': 16, }, 'UUID32Field': { 'type': 'input', 'minlength': 32, 'maxlength': 32, }, 'UUID36Field': { 'type': 'input', 'minlength': 36, 'maxlength': 36 }, 'DateTimeField': { 'type': 'datetime', 'format': "yyyy-MM-dd hh:mm:ss", 'valueFormat': "yyyy-MM-dd hh:mm:ss", }, 'DateField': { 'type': 'date', 'format': "yyyy-MM-dd", 'valueFormat': "yyyy-MM-dd", }, 'TimeField': { 'type': 'time', 'format': "hh:mm:ss", 'valueFormat': "hh:mm:ss", }, 'BooleanField': { 'type': 'radio', 'dicData': [ {'value': False, 'label': '否'}, {'value': True, 'label': '是'}, ] }, 'ManyRelatedField': { # 'type': 'select', 'type': 'array', # "multiple": True, 'required': False, }, } FIELD_TYPE_DEFAULT = { 'type': 'input', } def getTable(self, serializer: serializers.ModelSerializer = None): if not serializer: serializer = self.get_serializer() serializer_class = serializer.__class__ model = serializer_class.Meta.model title = model.__name__ if hasattr(model, 'Meta'): if hasattr(model.Meta, 'verbose_name'): title = model.Meta.verbose_name or '' column = self.getColumn(serializer) table = { 'title': title, 'page': True, 'align': 'center', 'menuAlign': 'center', 'columnBtn': True, 'menu': True, 'menuType': 'icon', 'addBtn': True, 'delBtn': True, 'editBtn': True, 'column': column } return table def getColumn(self, serializer: serializers.ModelSerializer = None): if not serializer: serializer = self.get_serializer() serializer_class = serializer.__class__ fields = serializer.get_fields() show_fields = getattr(serializer_class.Meta, 'show_fields', set()) hide_fields = getattr(serializer_class.Meta, 'hide_fields', set()) search_fields = getattr(serializer_class.Meta, 'search_fields', set()) sortable_fields = getattr(serializer_class.Meta, 'sortable_fields', set()) column = [] for prop in fields: field = fields[prop] field_type = field.__class__.__name__ info = { 'prop': prop, 'label': field.label or prop, 'hide': hide_fields == '__all__' or prop in hide_fields, 'search': search_fields == '__all__' or prop in search_fields, 'sortable': sortable_fields == '__all__' or prop in sortable_fields, 'width': 'auto', 'align': 'left', 'overHidden': False, } type_info = self.FIELD_TYPE_MAP.get(field_type, self.FIELD_TYPE_DEFAULT) info.update(type_info) allow_null = getattr(field, 'allow_null', False) allow_blank = getattr(field, 'allow_blank', False) allow_empty = getattr(field, 'allow_empty', False) read_only = getattr(field, 'read_only', False) write_only = getattr(field, 'write_only', False) if not any([allow_null, allow_blank, allow_empty]): rules = [{ 'required': True, 'message': f"""请输入{info['label']}""", 'trigger': "blur" }] info['rules'] = rules if read_only: info['editDisabled'] = True, info['clearable'] = False if not isinstance(field, (ManyRelatedField, RelatedField, PrimaryKeyRelatedField)): # 防止序列化该字段的关系模型所有数据 choices = getattr(field, 'choices', None) if choices: dicData = list(map(lambda choice: {'value': choice[0], 'label': choice[1]}, choices.items())) info['dicData'] = dicData info['type'] = 'select' column.append(info) return column