Django DRF:使用PrimaryKeyRelatedFields列表POST到CreateAPIView

时间:2018-06-13 22:20:26

标签: django django-rest-framework django-views

我在以下模型之间有多对一的关系

class Story(models.Model):

    id = models.CharField(max_length=12, primary_key=True)


class Article(models.Model):

    id = models.CharField(max_length=16, primary_key=True)
    title = models.CharField(max_length=500)
    address = models.URLField()

    story = models.ForeignKey(to=Story, blank=True, null=True, on_delete=models.CASCADE)

假设我成功地将几个文章对象发布到数据库。 我确定带有ids的文章

['1', '2', '3'] 

都是关于特定故事的报道。

我想通过POST方法创建一个Story到这样的

的CreateAPIView视图
POST http://127.0.0.1/news/story {articles': ['1', '2', '3']}

这是我的序列化程序

class StorySerializer(serializers.ModelSerializer):

     id = serializers.ReadOnlyField()
     articles = serializers.PrimaryKeyRelatedField(many=True, allow_empty=False, queryset=Article.objects.all())

     class Meta:
         model = Story
         fields = ('id', 'articles')

这是我的观点

class StoryList(generics.ListCreateAPIView):

    serializer_class = StorySerializer
    queryset = Story.objects.all()

我想确保1)文章存在。 2)在创建Story对象之前更新文章故事。

假设我按原样运行,我将收到以下错误:

  

在致电TypeError时获得Story.objects.create()。这可能是   因为序列化程序类上有一个可写字段而不是   Story.objects.create()的有效参数。你可能需要做   字段只读,或覆盖StorySerializer.create()方法   正确处理。

所以这是尝试覆盖create()方法:

    def create(self, validated_data):

        story_id = None

        for article_id in validated_data['articles']:
            article = Article.objects.get(id=article_id)
            story_id = article.story_id
            if story_id:
                break

        story = Story.objects.get(id=story_id) if story_id else Story.objects.create()

        for article_id in validated_data['articles']:
            article = Article.objects.get(id=article_id)
            article.story_id = story.id
            article.save()

        story.save()
        return story

    def update(self, instance, validated_data):
        return self.create(validated_data)

这里的想法是通过合并它们来确保没有重叠的故事。

当我尝试POST到此视图时,遇到DoesNotExist行引发的Article.objects.get(id=article_id)

我的问题是

1)次要:为什么我收到此错误

2) Major :在django中是否有更清晰/正确的方法来处理这样的用例?

谢谢

1 个答案:

答案 0 :(得分:0)

class StoryList(generics.ListCreateAPIView):

    serializer_class = StorySerializer
    query_set = Story.objects.all()

它应该是quertset而不是query_set

1)轻微:为什么我收到此错误

你给了一个不存在的非法article_id。

2)专业:在django中是否有更清晰/正确的方法来处理这样的用例?

drf-writable-nested可以在drf中处理嵌套写入。