当前位置: 代码迷 >> python >> 在Django Rest框架中创建视图中处理外键
  详细解决方案

在Django Rest框架中创建视图中处理外键

热度:97   发布时间:2023-06-13 14:14:09.0

我有两个模型:

class Foo(models.Model):
    name = models.CharField(max_length=64)

class Bar(models.Model):
    foo = models.ForeignKey(Foo)
    name = models.CharField(max_length=64)

和那些序列化器

class FooSerializer(serializers.ModelSerializer):
    class Meta:
        model = Foo
        fields = ('pk', 'name')

class BarSerializer(serializers.ModelSerializer):
    foo = ???
    class Meta:
        model = Bar
        fields = ('pk', 'foo', 'name')

我需要为Bar对象/bar/create一个api /bar/create ,例如:

  • 我只在输入json中提供Foo主键
  • 我用FooSerializer序列化的foo检索Bar对象。

因此,让我们考虑一下我在数据库中有这个Foo(pk=1, name='foo')对象,我想这样做:

  • 请求:
    • 开机自检/ bar /创建
    • content = {'foo': 1, 'name': 'bar'}
  • 响应
    • {'foo': {'pk': 1, 'name': 'foo'}, 'name': 'bar'}

我怎么能简单地做到这一点? 这样做是一种好习惯吗?

一种方法是将字段化为嵌套对象,并使别名化的嵌套对象为只读:

class BarSerializer(serializers.ModelSerializer):
    foo_obj = FooSerializer(required=False,read_only=True)
    class Meta:
        model = Bar
        fields = ('pk', 'foo', 'foo_obj', 'name')

如果存在foo ,则将其放置在Barfoo_obj字段中。 在客户端,您必须使foofoo_obj保持同步”,这确实很臭。

  1. 如何做到:一种实现方法是使用2个序列化器,您将根据请求类型进行选择:
    class BarSerializer(serializers.ModelSerializer):
        class Meta:
            model = Bar
            fields = ('pk', 'foo', 'name')

    class BarNestedSerializer(BarSerializer):
        class Meta(BarSerializer.Meta):
            depth = 2


    class BarView(generics.ListCreateAPIView):
        queryset = Bar.objects.all()

        def get_serializer_class(self):
            return BarNestedSerializer if self.action == 'list' else BarSerializer
  1. 应该如何完成:为Foo对象设置一条单独的路由,您将在前端缓存该路由,并根据ID显示其查找值。 归根结底,这实际上取决于您的用例,但是通常只有在绝对必要的情况下,才应该能够避免嵌套。