我有简单的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."
],
}
关于如何解决问题的任何想法吗?
答案 0 :(得分:1)
我稍微改变了创建功能。还向序列化器添加了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)
答案 1 :(得分:1)
简单胜于复杂:
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"
}