Django Rest Framework-有条件地使序列化器的字段为必需字段,或者不使用其他字段值

时间:2019-05-21 13:25:34

标签: python django django-models django-rest-framework

在我的DRF项目中,我有一个模型:

class Item(BaseModel):
    PRIVATE = 'PRIVATE'
    COMPANY = 'COMPANY'
    ACCOUNT_TYPES = (
        (PRIVATE, _('Private')),
        (COMPANY, _('Company')),
    )
    company_name = models.CharField(max_length=128, null=True, blank=True)
    person_name = models.CharField(max_length=128, null=True, blank=True)
    account_type = models.CharField(max_length=32, choices=ACCOUNT_TYPES)
    phone = models.CharField(max_length=128, null=True, blank=True)
    email = models.EmailField(max_length=128, null=True, blank=True)

和ItemSerializer在序列化器中,例如:

class ItemSerializer(serializers.ModelSerializer):
    class Meta:
        model = Item
        fields = ('account_type', 'company_name', 'person_name')

    def create(self, validated_data):
        print('ItemSerializer, create')
        print('validated_data:', validated_data)
        return super().create(validated_data)

    def validate(self, attrs):
        print('ItemSerializer validate, attrs:', attrs)
        return attrs

在模型中可以看到,有company_nameperson_name字段,在模型中都不是必需字段。

要创建项目,必须指定account_type。其为PRIVATECOMPANY

现在,在我的序列化器中,如果帐户类型是公司或私人,我想输入必填字段。例如,如果account_type为COMPANY,则我想使字段company_name为必需。如果account_type为PRIVATE,我想要求person_name

  1. 哪种方法是实现此目标的合适空间,我该怎么做?
  2. 也使用上述逻辑,我想在现场进行额外的验证。例如:是account_typePRIVATE并且person_name不为空,我想对person_name进行一些验证(检查其格式,长度等是否正确)

3 个答案:

答案 0 :(得分:0)

您可以使用将所有序列化字段作为参数接收的序列化器的validate方法,请参见here

答案 1 :(得分:0)

您可以定义两个序列化器PrivateSerializerCompanySerializer,然后在您看来,使用方法.get_serializer_class(),然后根据请求中发送的内容返回一个或另一个。

通过这种方式,您可以根据情况定义每个序列化程序验证。

答案 2 :(得分:0)

您可以使用def validate(self, data)来检查条件要求, 和 def validate_{field_name}(self, value) 进行额外验证:

class ItemSerializer(serializers.ModelSerializer):
    class Meta:
        model = Item
        fields = ('account_type', 'company_name', 'person_name')
        extra_kwargs = {
            'company_name': {'required': False},
            'person_name': {'required': False},
        }

    def validate(self, data):
        data_dict = dict(data)
        data_keys = data.keys()
        account_type= data_dict.get('account_type')
        if account_type == 'PRIVATE' and 'person_name' not in data_keys:
            raise serializers.ValidationError('person_name required when account_type is PRIVATE.')
        if account_type == 'COMPANY' and 'company_name' not in data_keys:
            raise serializers.ValidationError('company_name required when account_type is COMPANY.')
        return data

    def validate_person_name(self, value):
        if len(value) < 10:
            raise serializers.ValidationError('person_name must be at least 10 characters.')
        return value