我有一个django-rest-api应用程序,其模型为Record,Tag和Weight,其中Record和Tag通过Weight模型具有多对多关系:
# models.py
class Tag(models.Model):
image = models.ImageField(upload_to='tag_images', null=True, blank=True)
class Record(models.Model):
file = models.FileField(upload_to='record_files', null=True, blank=True)
class Weight(models.Model):
record = models.ForeignKey(
Record,
related_name='weights',
on_delete=models.CASCADE
)
tag = models.ForeignKey(
Tag,
related_name='weights',
on_delete=models.CASCADE
)
value = models.IntegerField()
class Meta:
unique_together = ('record', 'tag',)
记录和标签模型都具有FileField / ImageField参数。在我的REST API视图中,我想显示“记录详细信息”及其完整文件url,并显示所有相关“标签”及其完整图像url。这是我的序列化器的样子:
# serializers.py
class RecordSerializer(serializers.ModelSerializer):
tags = serializers.SerializerMethodField()
class Meta:
model = Record
fields = ('id', 'file', 'tags')
def get_tags(self, obj):
return TagSerializer(Tag.objects.filter(weights__in=obj.weights.all()), many=True).data
class TagSerializer(serializers.ModelSerializer):
class Meta:
model = Tag
fields = ('id', 'image')
问题在于,当我看到记录详细信息视图时,其文件url已完成,但标签图像url却不完整:
# record detail results
{
"id": 1,
"file": "http://127.0.0.1:8080/media/record_files/record00.mp3",
"tags": [
{
"id": 4,
"image": "/media/tag_images/image04.jpg"
},
{
"id": 10,
"image": "/media/tag_images/image10.jpg"
}
]
}
最后,我通过创建一个单独的标签列表视图来绕过该问题,即使在我的serializers.py中没有做任何改动,URL也完整了。
# record tag list results
[
{
"id": 4,
"image": "http://127.0.0.1:8080/media/tag_images/image04.jpg"
},
{
"id": 10,
"image": "http://127.0.0.1:8080/media/tag_images/image10.jpg"
}
]
我想无论如何这都是一个更干净的rest api解决方案(尽管我很确定我将不需要分别记录详细信息及其标签)。不过,这仍然使我感到困惑,为什么当数据是嵌套序列化程序的一部分时,URL不完整。这是应该的意思还是我做错了什么?
答案 0 :(得分:1)
似乎您可能找到了更好的解决方案,但以防万一您仍然感到好奇:您最初尝试的问题是将“嵌套”序列化程序调用放在了SerializerMethodField
中。声明nested serializer的通常方法是在设置实际字段时初始化序列化程序。在您的情况下,它看起来像这样:
class RecordSerializer(serializers.ModelSerializer):
tags = TagSerializer()
以这种方式执行操作时,TagSerializer
可以从父序列化程序推断上下文,而该上下文的一部分就是请求。然后在to_representation
的调用中build_absolute_uri
中使用它来生成您希望的完整URL。
答案 1 :(得分:0)