首页 > 解决方案 > Django Rest Framework - 序列化程序中带有查询参数的 URL

问题描述

我有 aStoryPost模型,其中 aPost属于 a Story。我想要一个 URL 来获取与给定故事相关联的所有帖子。

我能够覆盖get_querysetPostViewSet的,以便按故事过滤帖子,如http://localhost:8000/posts/?story=1/. 如果我直接输入 URL,这会很好地工作。现在我想在我的StorySerializer. 我希望能够获得看起来像这样的故事回复

[
    {
        "url": "http://localhost:8000/stories/1/",
        "title": "Hero's Journey",
        "openings": 0,
        "date_created": "2020-06-28T16:53:35.150630Z",
        "posts": "http://localhost:8000/posts/?story=1/"
    },
    {
        "url": "http://localhost:8000/stories/2/",
        "title": "Halo 3",
        "openings": 0,
        "date_created": "2020-06-28T18:17:12.973586Z",
        "posts": "http://localhost:8000/posts/?story=2/"
    }
]

这种东西有DRF支持吗?我试图在我的 中使用HyperlinkedIdentityFieldwith 'post-list'View StorySerializer,但我找不到可行的参数组合。我得到的当前异常是 AttributeError: 'Story' object has no attribute 'posts'

序列化器

class StorySerializer(serializers.HyperlinkedModelSerializer):
    posts = serializers.HyperlinkedIdentityField(
        view_name = 'post-list',
        many=True,
        lookup_field = 'pk',
        lookup_url_kwarg = 'story',
    )
    class Meta:
        model = models.Story
        fields = ['url', 'title', 'openings', 'date_created', 'posts']


class PostSerializer(serializers.HyperlinkedModelSerializer):
    class Meta:
        model = models.Post
        fields = ['url', 'story', 'user', 'text', 'date_created']

意见

class StoryViewSet(viewsets.ModelViewSet):
    queryset = models.Story.objects.all()
    serializer_class = serializers.StorySerializer


class PostViewSet(viewsets.ModelViewSet):
    queryset = models.Post.objects.all()
    serializer_class = serializers.PostSerializer

    def get_queryset(self):
        queryset = self.queryset
        story_id = self.request.query_params.get('story', None)
        if story_id is not None:
            queryset = queryset.filter(story=story_id)
        return queryset

楷模

class Story(models.Model):
    title = models.CharField(max_length=100)
    date_created = models.DateTimeField(default=timezone.now)
    openings = models.PositiveSmallIntegerField(default=0)
    participant = models.ManyToManyField(User)


class Post(models.Model):
    text = models.CharField(max_length=300)
    user = models.ForeignKey(
        User,
        on_delete=models.PROTECT)
    story = models.ForeignKey(
        Story,
        on_delete=models.PROTECT)
    date_created = models.DateTimeField(default=timezone.now)

标签: djangodjango-rest-framework

解决方案


我能够在这里找到一个很好的解决方案,覆盖 get_url 方法以将“pk”值直接映射到“故事”。 https://stackoverflow.com/a/27584761/7308261

from rest_framework.reverse import reverse
import urllib

class StoryPostsHyperlinkedIdentityField(serializers.HyperlinkedIdentityField):
    def get_url(self, obj, view_name, request, format):
        lookup_field_value = getattr(obj, self.lookup_field, None)
        result = '{}?{}'.format(
            reverse(view_name, kwargs={}, request=request, format=format),
            urllib.parse.urlencode({'story': lookup_field_value})
        )
        return result


class StorySerializer(serializers.HyperlinkedModelSerializer):
    posts = StoryPostsHyperlinkedIdentityField(
        view_name='post-list',
    )
    class Meta:
        model = models.Story
        fields = ['url', 'title', 'openings', 'date_created', 'posts']

推荐阅读