Ⅰ. Précautions pour la création et la mise à jour à l'aide de la sérialisation drf
① Lorsqu'un champ n'est pas obligatoire, le frontal transmet le champ avec la valeur "" chaîne vide. À ce stade, il signalera une erreur lors de sa création. Il n'y a aucun moyen pour le créer et l'invite Le champ doit transmettre une valeur.
Solution:
Ajoutez allow_blank = True à la séquence du champ
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)
② Règles de vérification de la sérialisation
1. Vérification de champ unique
class AvailAreaSerializer(serializers.ModelSerializer):
name = serializers.CharField(
validators=[UniqueValidator(
queryset=AvailArea.objects.filter(is_delete=False), message=u'name已存在')]
)
2. Vérification de plusieurs champs
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. Validateur personnalisé
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])
Ordre de pondération: validateur personnalisé> validation d'un seul champ> validation de plusieurs champs.
Remarque: La création et la mise à jour de la liste de séquences seront vérifiées.
Si vous souhaitez vérifier lors de la création, et non lors de la mise à jour, de la méthode de suggestion personnelle Réécrire la méthode de création
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
Ⅱ. Filtrage de liste
1. Filtrage de champ d'origine
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. Le champ unique du front-end correspond à la recherche multi-champs back-end.
Une zone de saisie sur le front-end, recherche en fonction du destinataire et du numéro de téléphone portable, et passe dans le récepteur comme le 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. Filtrage de champ personnalisé
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)
Inconvénients: lorsque certains champs de filtre sont obtenus en fonction de la demande, il n'y a aucun moyen de les filtrer. Deuxièmement, le contenu de la recherche, vous souhaitez modifier la valeur du champ dans le résultat de la recherche en fonction de certaines valeurs de champ du serveur frontal, il n'est pas possible de le modifier et le paramètre de valeur d'attribut n'est pas pris en charge. Seul le list est réécrite
. Ⅲ. Ajouter des champs personnalisés renvoyés par sérialisation
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 sérialisation renvoie des champs personnalisés, pas besoin de méthode de re-représentation (self, instance)
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='该系统环境已配置过发布流程'
)
]
Ⅳ. Notez que la méthode personnalisée accepte les paramètres
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)})
Remarque: Lorsque la méthode personnalisée est une requête POST, utilisez request.data pour accepter, n'utilisez pas request.body pour accepter. Lors d'un développement local, request.body peut accepter la valeur transmise par le frontal. Lorsqu'il est déployé en ligne, request. body est la valeur qui ne peut pas être récupérée depuis le frontal, utilisez request.data.
Et la valeur de request.data est directement json, pas besoin de json.loads ().