【问题标题】:Override required field in validator django DRF覆盖验证器 django DRF 中的必填字段
【发布时间】:2020-07-15 06:09:31
【问题描述】:

我有简单的 EmployeeSkill 和 Skill 模型:


class EmployeeSkill(models.Model):

    # this is required
    employee = models.ForeignKey(
        Employee, on_delete=models.CASCADE
    )

    # this is required
    skill = models.ForeignKey(
        Skill, on_delete=models.CASCADE
    )

    def skill_name(self):
        return self.skill.name


class Skill(models.Model):

    # this is required
    name = models.CharField(max_length=255, unique=True)

我想在模型中保留 EmployeeSkill 所需的技能属性,但我想在序列化程序中启用仅传递技能名称,这将获取或创建适当的技能。这是我的序列化程序:


class EmployeeSkillSerializer(serializers.ModelSerializer):

    class Meta:
        fields = (
            "id",
            "employee",
            "skill",
            "skill_name",
        )
        model = EmployeeSkill
        extra_kwargs = {
            "skill": {"required": False},
        }


    def validate_skill(self, value):
        """ custom validator for skill. skill can be empty if skill_name is valid """

        if value is None:
            skill_name = getattr(self, "skill_name", None)
            if not (skill_name and type(skill_name) is str):
                raise serializers.ValidationError(
                    "if no skill is provided, skill_name should be a valid string"
                )

        elif not type(value) is Skill:
            raise serializers.ValidationError("skill must be of type Skill or None")

        return value


    def create(self, validated_data):
        if (not self.skill) and self.skill_name:
            validated_data["skill"] = Skill.objects.get_or_create(skill_name=self.skill_name)[0]
        super().create(validated_data)

问题是,我还是报错:

{
    "skill": [
        "This field may not be null."
    ],
}

知道如何解决我的问题吗?

【问题讨论】:

    标签: python django validation django-rest-framework serialization


    【解决方案1】:

    我稍微改变了创建函数。还在序列化程序中添加了技能名称字段。

    from rest_framework import serializers
    from webtest.models import EmployeeSkill, Skill
    
    
    class EmployeeSkillSerializer(serializers.ModelSerializer):
        skill_name = serializers.CharField()
    
        class Meta:
            fields = (
                "id",
                "employee",
                "skill",
                "skill_name",
            )
            model = EmployeeSkill
            extra_kwargs = {
                "skill": {"required": False},
            }
    
    
        def validate_skill(self, value):
            """ custom validator for skill. skill can be empty if skill_name is valid """
    
            if value is None:
                skill_name = getattr(self, "skill_name", None)
                if not (skill_name and type(skill_name) is str):
                    raise serializers.ValidationError(
                        "if no skill is provided, skill_name should be a valid string"
                    )
    
            elif not type(value) is Skill:
                raise serializers.ValidationError("skill must be of type Skill or None")
    
            return value
    
    
        def create(self, validated_data):
            if not validated_data.get('skill') and validated_data.get('skill_name'):
                validated_data["skill"] = Skill.objects.get_or_create(name=validated_data['skill_name'])[0]
            if 'skill_name' in validated_data:
                del validated_data['skill_name']
            return super().create(validated_data)
    

    【讨论】:

      【解决方案2】:

      简单胜于复杂:

      class EmployeeSkillSerializer(serializers.ModelSerializer):
          skill = serializers.CharField(source='skill.name')
      
          class Meta:
              fields = ("id", "employee", "skill")
              model = EmployeeSkill
      
          def create(self, validated_data):
              skill_name = validated_data.pop('skill', {}).get('name', '')
              skill_instance, created = Skill.objects.get_or_create(name=skill_name)
              validated_data['skill'] = skill_instance
              return super().create(validated_data)

      示例 JSON 有效负载,

      {
          "employee": "Martin Faucheux",
          "skill": "Programming"
      }
      

      【讨论】:

        猜你喜欢
        • 2013-03-23
        • 2010-11-26
        • 2011-11-24
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多