Résumé de l'apprentissage et de l'utilisation du framework django rest

Ⅰ. 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 ().

Je suppose que tu aimes

Origine blog.csdn.net/qq_42631707/article/details/106915583
conseillé
Classement