抱歉这个奇怪的标题。
我有2个型号:
class TranslationWord(models.Model):
translation = models.TextField(unique=True)
created_at = models.DateTimeField(auto_now_add=True)
updated_at = models.DateTimeField(auto_now=True)
class TranslationByUser(models.Model):
synset = models.ForeignKey(Synset)
user = models.ForeignKey(User)
translation = models.ForeignKey(TranslationWord)
第一个应该基本上只是保存单词。第二个应该是获得用户的输入。如果单词存在于第一个类中,则简单地存储外键值。如果它不存在,我想首先创建一个TranslationWord实例,然后将外键添加到第二个类。
我正在使用Django Rest Framework完成所有这些工作,所以我很难过。
目前,我已经拥有这2个模型,2个序列化程序(都是ModelSerializer的实例),还有一个保存它的视图(ListCreateAPIView)。
我该怎么做呢?
答案 0 :(得分:0)
这些基本上是在ModelViewSet创建方法中创建成功验证对象的步骤(它在CreateModelMixin中定义):
if serializer.is_valid():
self.pre_save(serializer.object)
self.object = serializer.save(force_insert=True)
self.post_save(self.object, created=True)
headers = self.get_success_headers(serializer.data)
return Response(serializer.data, status=status.HTTP_201_CREATED,
headers=headers)
这意味着您可以在ViewSet for TranslationByUser中覆盖您的操作的pre_save,将属性设置为对象中的副作用:
def pre_save(self, obj):
#get your_translation_word from obj or self.kwargs
your_translation_word = get_translation_word()
translation = TranslationWord(translation=your_translation_word)
translation.save()
setattr(obj, 'translation', translation)
#if you also want to support Update, call super method
super(TranslationByUserViewSet, self).pre_save(obj)
您可以尝试的另一件事是将TranslationWordSerializer定义为TranslationByUserSerializer中的嵌套字段。 docs中介绍了此主题。不确定DRF是否处理有关创建的所有内容。我只使用多表继承测试了这种行为(并且它可以工作)。
答案 1 :(得分:0)
无论如何,对于任何好奇的人,我在Serializer中创建了一个只写字段,并用它在restore_object方法中创建实例。
class MySerializer(serializers.ModelSerializer):
user = UserSerializer(required=False)
translation = TranslationLemmaSerializer(required=False)
translation_text = serializers.WritableField(required=False, write_only=True)
class Meta:
model = TranslationByUser
fields = ('id','user','synset', 'translation', 'translation_text',)
read_only_fields = ('id', 'created_at', 'updated_at',)
def restore_object(self, attrs, instance=None):
print attrs
if instance is not None:
instance.synset = attrs.get('synset', instance.synset)
return instance
translation_text = attrs.get('translation_text')
del attrs['translation_text'] #delete non-model attribute before actually creating it
translationHIT = TranslationByUser(**attrs) #create model here
translation_id = None
try:
translation_instance = TranslationWord.objects.get(translation=translation_text) #check if translationWord is already present
except:
translation_instance = TranslationWord(translation=translation_text)
translation_instance.save() #otherwise, create it
TranslationByUser.translation = translation_instance
print attrs
return TranslationByUser
def get_validation_exclusions(self,instance=None):
exclusions = super(MySerializer, self).get_validation_exclusions()
return exclusions + ['user', 'translation']