【发布时间】:2016-01-29 13:16:15
【问题描述】:
我正在与使用 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 上的方法轻松检索相关对象,但这很少会导致循环依赖,因为我很少从另一端。
当我尝试将 serializers 添加到一堆时,问题就开始了。为了使 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
但这感觉就像一个 ugly、ugly、uuuugly hack。
您能分享一下您遇到类似问题的经验吗?
谢谢!
【问题讨论】:
-
谢谢你的丑陋,丑陋,uuuugly hack
-
您也可以暂时使用 BaseSerializer,然后在可用时用适当的序列化程序覆盖它
标签: django serialization django-rest-framework python-import circular-dependency