重写验证器Django DRF中的必填字段

2024-06-10 05:18:39 发布

您现在位置:Python中文网/ 问答频道 /正文

我有简单的员工技能和技能模型:


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的skill属性,但我想在序列化程序中只传递一个skill名称,这将获得或创建适当的skill。这是我的序列化程序:


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."
    ],
}

有没有办法解决我的问题


Tags: nameselfifisvaluemodelsdefrequired
2条回答

我稍微更改了创建函数。还向序列化程序添加了skill_name字段

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)

简单比复杂好:

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"
}

相关问题 更多 >