django-vue-admin/dvadmin-backend/apps/op_drf/mixins.py

274 lines
8.9 KiB
Python

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