如何在 Django REST Framework 中验证模型

77 阅读2分钟

在一个 Django REST Framework 项目中,有一个模型包含四个查找表。其中一个查找表用于指定类型。根据类型(总共有四种),字段的要求会发生变化。例如,如果类型是“Survey”,则需要number_of_unique_contacts字段,但对其他类型而言则不需要。

开发人员考虑使用多个表和基于建模继承的数据库模式。但由于只有四种类型,并且只有 6 个字段作为“按上下文要求”以类型为依据发挥作用,因此这没有意义。也就是说,开发人员愿意在 Django 中使用多个模型,但更希望 REST 框架仅呈现一个 URI(而不是每个类型一个)。

目前的问题是:在 POST/PUT 请求中验证模型的最佳方法是什么?是否应该选择另一个数据库架构(如前所述,认为自己是对的)?还是应该重新构建 Python 模型(仍然是具有四个查找的一个主类)?

开发人员是 Django 和 Python 的新手,因此希望大家温柔一点(拥有 .NET/Java 背景)。提前感谢大家的帮助。

以下是一些相关的代码(说实话,代码可能无关紧要,因为这更像是一个设计问题,但总是觉得不提供代码很奇怪——至少为了提供背景):

class MySerializer(serializers.ModelSerializer):
    proposal_side = serializers.SlugRelatedField(many=False, read_only=False, slug_field='proposal_side')
    my_proposal_type = serializers.SlugRelatedField(many=False, read_only=False, slug_field='proposal_type')
    my_proposal_delivery_type = serializers.SlugRelatedField(many=False, read_only=False, slug_field='delivery_type')
    my_survey_method = serializers.SlugRelatedField(many=False, read_only=False, slug_field='method')
    class Meta:
        model = diliModels.Proposal
        fields = (
            'id'
            ,'my_proposal_side'
            ,'my_proposal_type'
            ,'number_of_participants'
            ,'cost_per_participants'
            ,'minimum_dollar_commitment'
            ,'commercial_terms'
            ,'is_publicly_visible'
            ,'is_anonymous'
            ,'is_republish'
            ,'name'
            ,'my_delivery_type'
            ,'my_survey_method'
            ,'number_of_unique_contacts'
            ,'availability_start'
            ,'availability_end'
            ,'location_country'
            ,'location_city'
            ,'location_state'
            ,'description'
            ,'desired_meetings'
        )


class MyViewSet(viewsets.ModelViewSet):
    paginate_by = 100

    queryset = myModels\
        .MyProposal\
        .objects\
        .prefetch_related('blah')
    print 'SQL::MyViewSet: ' + str(queryset.query)
    serializer_class = serializers.MySerializer

2. 解决方案

一种方法是将 validate 方法添加到序列化器类中。

class MySerializer(serializers.ModelSerializer):
    proposal_side = serializers.SlugRelatedField(many=False, read_only=False, slug_field='proposal_side')
    my_proposal_type = serializers.SlugRelatedField(many=False, read_only=False, slug_field='proposal_type')
    my_proposal_delivery_type = serializers.SlugRelatedField(many=False, read_only=False, slug_field='delivery_type')
    my_survey_method = serializers.SlugRelatedField(many=False, read_only=False, slug_field='method')
    class Meta:
        model = diliModels.Proposal
        fields = (
            'id'
            ,'my_proposal_side'
            ,'my_proposal_type'
            ,'number_of_participants'
            ,'cost_per_participants'
            ,'minimum_dollar_commitment'
            ,'commercial_terms'
            ,'is_publicly_visible'
            ,'is_anonymous'
            ,'is_republish'
            ,'name'
            ,'my_delivery_type'
            ,'my_survey_method'
            ,'number_of_unique_contacts'
            ,'availability_start'
            ,'availability_end'
            ,'location_country'
            ,'location_city'
            ,'location_state'
            ,'description'
            ,'desired_meetings'
        )

    def validate(self, attrs):
         raise serializers.ValidationError("error")
         return attrs

这样,就可以在序列化器类中执行自定义验证。