我有简单的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."
],
}
你知道我该怎么解决我的问题吗?
我稍微更改了创建函数。还向序列化程序添加了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"
}