什么是写入与ForeignKey相关项已存在的嵌套序列化程序的最佳方法?
示例 - 我有一对多的调查模型和SurveyReponse模型。尚未创建调查模型的新SurveyResponse模型的POST无问题,并且还没有定义特定调查模型的模型的POST,我默认为特定的调查模型。但是,尝试提供该字段似乎会导致验证问题类似于过去提出的问题:https://github.com/encode/django-rest-framework/issues/2996 似乎只是添加验证器= []修复了我的问题。
到目前为止我做了什么:
我设置我的SurveyReponse.create()方法是为了发布一个SurveyResponse提供NO Survey,并将其保存到默认的Survey。
这非常有效。
{ "rating": 10 }
创建一个新的SurveyReponse对象,并将其与名为“默认调查名称”的调查相关联
我还想做什么: 我希望能够提供一个特定的调查,以便将我的SurveyReponse联系起来。
{
"rating": 10,
"survey": {"name": "Other Survey Name"}
}
如果调查尚不存在,这对我当前的代码工作正常,但是,如果调查已经存在,我点击了唯一标识符重复错误
{
"survey": {
"name": [
"survey with this name already exists."
]
}
}
我如何解决这个问题? 删除此行,
survey = SurveySerializer(required=False)
我能够做我想做的事,但是当我希望能够提供名称时,我必须只提供资源的URL。 (除非这个完整的想法是反模式或某种东西,在这种情况下,我应该总是只是写入/ survey /对象)
抽样调查和调查回复:
高级模特:
class Survey(models.Model):
created = models.DateTimeField(auto_now_add=True)
name = models.CharField(max_length=255, unique=True)
creator = models.ForeignKey(
'auth.User',
related_name='survey',
to_field='id',
null=True,
)
class SurveyResponse(models.Model):
"""Response to the Survey"""
survey = models.ForeignKey(Survey, blank=True)
created = models.DateTimeField(auto_now_add=True)
rating = models.IntegerField(blank=False)
creator = models.ForeignKey(
'auth.User',
related_name='survey_response',
to_field='id',
null=True,
)
串行器
class SurveySerializer(serializers.HyperlinkedModelSerializer):
creator = serializers.ReadOnlyField(source='creator.username')
class Meta:
model = Survey
fields = '__all__'
class SurveyResponseSerializer(serializers.HyperlinkedModelSerializer):
'''Question Serializer'''
creator = serializers.ReadOnlyField(source='creator.username')
survey = SurveySerializer(required=False)
def create(self, validated_data):
default_survey_name = "Default Survey Name"
survey_data = validated_data.pop('survey', None)
if survey_data is None:
try:
survey = Survey.objects.get(name=default_survey_name)
validated_data['survey'] = survey
except:
print("Unable to get Survey, creating a new one")
survey = Survey.objects.create(
name=default_survey_name,
description=default_survey_name,
creator=self.context['request'].user
)
validated_data['survey'] = survey
else:
survey, survey_created = Survey.objects.get_or_create(**survey_data)
validated_data['survey'] = survey
instance = self.Meta.model(**validated_data)
instance.save()
return instance
答案 0 :(得分:0)
我最终对Serializer进行了一系列更改以删除验证程序,并在创建和更新期间手动执行名称验证。让我知道是否有更惯用的方法!
class SurveySerializer(serializers.HyperlinkedModelSerializer):
creator = serializers.ReadOnlyField(source='creator.username')
def create(self, validated_data):
if Survey.objects.filter(name=self.validated_data['name']).exists():
raise serializers.ValidationError("A survey with this name already exists")
return Survey.objects.create(**validated_data)
def update(self, instance, validated_data):
all_other_survey = Survey.objects.exclude(name=instance.name)
if all_other_survey.filter(name=self.validated_data['name']).exists():
raise serializers.ValidationError("A survey with this name already exists (Not counting this instance)")
else:
instance.name = self.validated_data['name'] or instance.name
instance.save()
return instance
class Meta:
model = Survey
fields = '__all__'
extra_kwargs = {
'name': {
'validators': [],
}
}