嵌套序列化程序中的不完整媒体 url
Incomplete media url in nested serializers
我有一个 django-rest-api 应用程序,其中包含模型 Record、Tag 和 Weight,其中 Record 和 Tag 通过权重模型具有多对多关系:
# 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"
}
]
}
最后,我通过创建一个单独的标签列表视图绕过了这个问题,现在 url 已经完成,尽管我的 serializers.py.
# 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 不完整仍然让我感到困惑。这是它的本意还是我做错了什么?
看起来您可能找到了更好的解决方案,但以防万一您仍然好奇:您最初尝试的问题是您将 "nested" 序列化程序调用放在 SerializerMethodField
中。声明 nested serializer 的通常方法是在设置实际字段时初始化序列化程序。在您的情况下,它看起来像这样:
class RecordSerializer(serializers.ModelSerializer):
tags = TagSerializer()
当您这样做时,TagSerializer
可以从父序列化程序推断上下文,并且该上下文的一部分是请求。然后在 to_representation
调用 build_absolute_uri
中使用它来生成您希望的完整 url。
在您的视图中像这样初始化您的序列化程序:
serialized_store = StoreSerializer(store, context={"request": request})
您需要覆盖方法:
def get_serializer_context(self):
return {'request': self.request}
我有一个 django-rest-api 应用程序,其中包含模型 Record、Tag 和 Weight,其中 Record 和 Tag 通过权重模型具有多对多关系:
# 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"
}
]
}
最后,我通过创建一个单独的标签列表视图绕过了这个问题,现在 url 已经完成,尽管我的 serializers.py.
# 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 不完整仍然让我感到困惑。这是它的本意还是我做错了什么?
看起来您可能找到了更好的解决方案,但以防万一您仍然好奇:您最初尝试的问题是您将 "nested" 序列化程序调用放在 SerializerMethodField
中。声明 nested serializer 的通常方法是在设置实际字段时初始化序列化程序。在您的情况下,它看起来像这样:
class RecordSerializer(serializers.ModelSerializer):
tags = TagSerializer()
当您这样做时,TagSerializer
可以从父序列化程序推断上下文,并且该上下文的一部分是请求。然后在 to_representation
调用 build_absolute_uri
中使用它来生成您希望的完整 url。
在您的视图中像这样初始化您的序列化程序:
serialized_store = StoreSerializer(store, context={"request": request})
您需要覆盖方法:
def get_serializer_context(self):
return {'request': self.request}