Ⅰ. Precauciones para la creación y actualización mediante serialización drf
① Cuando un campo no es obligatorio, el front-end pasa el campo con el valor "" cadena vacía. En este momento, informará de un error cuando se cree. No hay forma para crearlo, y solicitar esto El campo debe pasar un valor.
Solución:
Agregue allow_blank = True a la secuencia del campo
class ApplySerializer(serializers.ModelSerializer):
last_version = serializers.CharField(required=False, allow_blank=True)
approve_second = serializers.CharField(required=False, allow_blank=True)
task_name = serializers.CharField(required=False, allow_blank=True)
②Reglas de verificación de serialización
1. Verificación de campo único
class AvailAreaSerializer(serializers.ModelSerializer):
name = serializers.CharField(
validators=[UniqueValidator(
queryset=AvailArea.objects.filter(is_delete=False), message=u'name已存在')]
)
2. Comprobación de varios campos
class CodeConfigSerializer(serializers.ModelSerializer):
bk_id = serializers.IntegerField(required=True)
class Meta:
model = CodeConfig
fields = '__all__'
validators = [
UniqueTogetherValidator(
queryset=CodeConfig.objects.all(),
fields=(
'bk_type', 'bk_code',
),
message='该类型编码已被使用'
)
]
3. Validador personalizado
key_validator = RegexValidator(
re.compile('^[_a-zA-Z0-9]+$'),
message=_(u'请输入合法编码:英文数字及下划线'),
code='invalid',
)
class DictDataSerializer(serializers.ModelSerializer):
"""数据字典数据项序列化"""
key = serializers.CharField(required=True, error_messages={'blank': _(u"编码不能为空")}, max_length=LEN_LONG,
validators=[key_validator])
Orden de peso: validador personalizado> validación de campo único> validación de campo múltiple.
Nota: La creación y actualización de la lista de secuencia será verificada.
Si desea verificar al crear, no al actualizar, método de sugerencia personal Vuelva a escribir el método de creación
class ProStoreConfigSerializer(serializers.ModelSerializer):
class Meta:
model = ProStoreConfig
exclude = ('is_deleted',)
def create(self, validated_data):
if not result:
raise serializers.ValidationError("制品库配置账户密码错误")
queryset = ProStoreConfig.objects.all()
if queryset.count():
raise serializers.ValidationError("制品库配置已配置过了")
else:
instance = super(ProStoreConfigSerializer, self).create(validated_data=validated_data)
return instance
Ⅱ. Filtrado de listas
1. Filtrado de campos originales
class BasicConfigFilter(django_filters.FilterSet):
bk_biz_id = django_filters.Filter(name='bk_biz_id')
bk_cluster_id = django_filters.Filter(name='bk_cluster_id')
bk_module_id = django_filters.Filter(name='bk_module_id')
class Meta:
model = BasicConfig
fields = '__all__'
2. El campo único de front-end corresponde a la búsqueda de múltiples campos de back-end.
Un cuadro de entrada en el front-end, busca según el destinatario y el número de teléfono móvil, y pasa al receptor como el back-end
class NotifyLogFilter(django_filters.FilterSet):
receiver = django_filters.Filter(method="filter_receiver", help_text="接收者匹配")
class Meta:
model = NotifyLog
fields = '__all__'
def filter_receiver(self, queryset, name, value):
return queryset.filter(Q(receiver_name__icontains=value) | Q(receiver_phone__icontains=value))
3. Filtrado de campos personalizados
class ApplyFilter(django_filters.FilterSet):
bk_biz_id = django_filters.Filter(name='bk_biz_id', method="filter_by_bk_biz_id")
bk_cluster_id = django_filters.Filter(name='bk_cluster_id', method="filter_by_bk_cluster_id")
bk_module_id = django_filters.Filter(name='bk_module_id', method="filter_by_bk_module_id")
now_version = django_filters.Filter(name="now_version", lookup_expr="icontains")
creator = django_filters.Filter(name="creator", method="filter_by_creator")
class Meta:
model = Apply
fields = '__all__'
def filter_by_creator(self, queryset, name, value):
if value == "admin":
return queryset
else:
return queryset.filter(creator=value)
def filter_by_bk_biz_id(self, queryset, name, value):
return queryset.filter(basic_config__bk_biz_id=value)
def filter_by_bk_cluster_id(self, queryset, name, value):
return queryset.filter(basic_config__bk_cluster_id=value)
def filter_by_bk_module_id(self, queryset, name, value):
return queryset.filter(basic_config__bk_module_id=value)
Desventajas: cuando se obtienen algunos campos de filtro en función de la solicitud, no hay forma de filtrarlos. En segundo lugar, el contenido de la búsqueda, desea cambiar el valor del campo en el resultado de la búsqueda de acuerdo con algunos valores de campo de la interfaz, no es posible cambiarlo y la configuración del valor del atributo no es compatible. Solo el el método de lista se reescribe
. Ⅲ. Agregar campos personalizados devueltos por serialización
class BasicConfig(Model):
bk_biz_id = models.IntegerField(_('业务id'), null=True)
bk_cluster_id = models.IntegerField(_('集群id'), null=True)
bk_module_id = models.IntegerField(_('模块id'), null=True)
publish_count = models.IntegerField(_('版本发布次数'), default=1)
# 0 未启用 1 已启用
status = models.BooleanField(_('启用状态'), default=0)
class Meta:
app_label = "configs"
verbose_name = _("基础配置")
verbose_name_plural = _("基础配置")
@property
def bk_biz_name(self):
bk_biz_name, _, _ = self.get_topo_data
return bk_biz_name
@property
def bk_cluster_name(self):
_, bk_cluster_name, _ = self.get_topo_data
return bk_cluster_name
@property
def bk_module_name(self):
_, _, bk_module_name = self.get_topo_data
return bk_module_name
@property
def get_topo_data(self):
result = cache.get(CACHE_BIZ_TOPOLOGY_NAME)
if not result:
result = get_biz_topology()
data = result.get(self.bk_biz_id)
bk_biz_name = data.get('bk_inst_name')
bk_cluster_name = None
bk_module_name = None
for i in data.get('child'):
if i.get('bk_inst_id') == self.bk_cluster_id:
bk_cluster_name = i.get('bk_inst_name')
for j in i.get('child'):
if j.get('bk_inst_id') == self.bk_module_id:
bk_module_name = j.get('bk_inst_name')
return bk_biz_name, bk_cluster_name, bk_module_name
@property
def process_config(self):
process_config_obj = ProcessConfig.objects.get(basic_config=self)
return model_to_dict(process_config_obj)
@property
def version_config(self):
version_config_obj = VersionConfig.objects.get(basic_config=self)
return model_to_dict(version_config_obj)
@property
def approve_config(self):
approve_config_obj = ApproveConfig.objects.get(basic_config=self)
return model_to_dict(approve_config_obj)
@property
def bk_biz_code(self):
biz_obj = CodeConfig.objects.filter(bk_id=self.bk_biz_id, bk_type=BIZ)
return biz_obj[0].bk_code if biz_obj else None
@property
def bk_cluster_code(self):
cluster_obj = CodeConfig.objects.filter(bk_id=self.bk_cluster_id, bk_type=CLUSTER)
return cluster_obj[0].bk_code if cluster_obj else None
@property
def bk_module_code(self):
module_obj = CodeConfig.objects.filter(bk_id=self.bk_module_id, bk_type=MODULE)
return module_obj[0].bk_code if module_obj else None
def code_version(self, date_time):
code_version = \
str(self.bk_biz_code) \
+ date_time + str(self.bk_module_code) + "." + str(self.publish_count)
return code_version
La serialización devuelve campos personalizados, no es necesario volver a representar el método (auto, instancia)
class BasicConfigSerializer(serializers.ModelSerializer):
bk_biz_id = serializers.IntegerField(required=True)
bk_cluster_id = serializers.IntegerField(required=True)
bk_module_id = serializers.IntegerField(required=True)
class Meta:
model = BasicConfig
fields = ('id', 'bk_biz_id', 'bk_cluster_id', 'bk_module_id',
'bk_biz_name', 'bk_cluster_name', 'bk_module_name',
'bk_biz_code', 'bk_cluster_code', 'bk_module_code',
'process_config', 'version_config', 'approve_config',
'status', 'publish_count',
'updated_by', 'update_at',
'creator', 'create_at'
)
validators = [
UniqueTogetherValidator(
queryset=BasicConfig.objects.filter(is_deleted=0),
fields=(
'bk_biz_id', 'bk_cluster_id', 'bk_module_id'
),
message='该系统环境已配置过发布流程'
)
]
Ⅳ. Tenga en cuenta que el método personalizado acepta parámetros
class ProcessConfigViewSet(component_viewsets.ModelViewSet):
serializer_class = ProcessConfigSerializer
queryset = ProcessConfig.objects.all()
@list_route(methods=['POST'], url_path='get_topology_data')
def get_topology_data(self, request):
"""从缓存中获取业务拓扑"""
# params = {'bk_biz_id': 2}
params = request.data
result = cache.get(CACHE_BIZ_TOPOLOGY_NAME)
if not result:
result = get_biz_topology()
result = result.get(params.get('bk_biz_id')).get('child')
return Response({"items": result, "count": len(result)})
Nota: Cuando el método personalizado es una solicitud POST, use request.data para aceptar, no use request.body para aceptar. Cuando se desarrolla localmente, request.body puede aceptar el valor pasado por la interfaz. Cuando se implementa en línea, request. body es el valor que no se puede recuperar de la interfaz, use request.data.
Y el valor de request.data es directamente json, sin necesidad de json.loads ().