gpt4 book ai didi

django - Django Rest Framework 序列化器中的循环依赖

转载 作者:行者123 更新时间:2023-12-02 12:08:58 25 4
gpt4 key购买 nike

我在使用 Django Rest Framework 3 编写的 Web API 中与序列化器内的循环依赖作斗争。虽然我知道项目中的循环依赖几乎总是糟糕设计的标志,但我找不到一种合适的方法避免它而不会使应用程序成为一个巨大的整体噩梦。

一个简单的精简示例足以很好地说明我遇到类似问题的所有地方所发生的情况。

让我们在两个应用程序中有两个简单的模型:

个人资料应用

# profiles/models.py

from images.models import Image

class Profile(models.Model):
name = models.CharField(max_length=140)

def recent_images(self):
return Image.objects.recent_images_for_user(self)

图像应用

# images/models.py

class Image(models.Model):
profile = models.ForeignKey('profiles.Profile')
title = models.CharField(max_length=140)

遵循胖模型的原则,我经常在模型中使用多个导入,以便使用 Profile 上的方法轻松检索相关对象,但这很少会导致循环依赖,因为我很少从另一端。

当我尝试将序列化器添加到序列中时,问题就开始了。为了使 API 占用空间较小并将必要的调用量限制在最低限度,我想在两端以简化形式序列化一些相关对象。

我希望能够在 /profile 端点上检索配置文件,该端点将包含有关用户嵌套创建的一些最近图像的简化信息。另外,当从 /images 端点检索图像时,我希望将配置文件信息嵌入到图像 JSON 中。

为了实现这一目标并避免递归嵌套,我有两个序列化器 - 对于两个应用程序,一个序列化器可以嵌套相关对象,另一个则不嵌套。

个人资料应用

# profiles/serializers.py

from images.serializers import SimplifiedImageSerializer

class SimplifiedProfileSerializer(serializers.Serializer):
name = serializers.CharField()

class ProfileSerializer(SimplifiedProfileSerializer):
recent_images = SimplifiedImageSerializer(many=True)

图像应用

# images/serializers.py

from profiles.serializers import SimplifiedProfileSerializer

class SimplifiedImageSerializer(serializers.Serializer):
title = serializers.CharField()

class ImageSerializer(SimplifiedImageSerializer):
profile = SimplifiedProfileSerializer()

预期的行为是获得以下 JSON 结果:

配置文件应用程序位于/profiles

[{
'name': 'Test profile',
'recent_images': [{
'title': 'Test image 1'
}, {
'title': 'Test image 2'
}]
]]

图像应用程序位于/images

[{
'title': 'Test image 1',
'profile': {
'name': 'Test profile'
}
},
{
'title': 'Test image 2',
'profile': {
'name': 'Test profile'
}
}]

但后来我因循环导入序列化器而碰壁。

我觉得将这两个应用程序合二为一绝对不是一条可行的道路 - 毕竟,图像与用户个人资料完全不同。

在我看来,序列化器也应该属于它们各自的应用程序。

到目前为止,我发现解决这个问题的唯一方法是在方法中导入,如下所示:

class ImageSerializer(SimplifiedProfileSerializer):
profile = SerializerMethodField()

def get_profile(self, instance):
from profiles.serializers import SimplifiedProfileSerializer
return SimplifiedProfileSerializer(instance.profile).data

但这感觉就像是一个丑陋丑陋uuuugly黑客。

您能分享一下您遇到类似问题的经验吗?

谢谢!

最佳答案

在我看来,您的代码很好,因为您没有逻辑循环依赖。

您的 ImportError 仅因 import() 在调用时评估整个文件的顶级语句的方式而引发。

然而,在Python中没有什么是不可能的......

如果您确实希望导入内容位于顶部,有一种解决方法:

来自 David Beazley 的精彩演讲 Modules and Packages: Live and Let Die! - PyCon 20151:54:00,这是Python中处理循环导入的方法:

try:
from images.serializers import SimplifiedImageSerializer
except ImportError:
import sys
SimplifiedImageSerializer = sys.modules[__package__ + '.SimplifiedImageSerializer']

这会尝试导入SimplifiedImageSerializer,如果引发ImportError,因为它已经导入,它将从导入缓存中提取它。

PS:您必须用 David Beazley 的声音阅读整篇文章。

关于django - Django Rest Framework 序列化器中的循环依赖,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/33413523/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com