You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何在Django Rest视图中获取媒体文件的完整URL

Django函数视图生成媒体文件完整URL的解决方法

问题场景

我针对Article模型编写了函数视图,但返回结果里的cover字段是相对路径(例如"/media/article/artice_cover_NkOUuZ7vH3zEejCgV.jpg"),需要改成包含主机名的完整URL(例如"http://localhost:8000/media/article/artice_cover_NkOUuZ7vH3zEejCgV.jpg")。使用ModelViewSet时能自动生成完整URL,但函数视图无法直接实现,相关代码如下:

函数视图代码

@api_view(["GET"])
def article_grid_list(request):
    # 从数据库获取数据
    data = Articles.objects.all().order_by("-created_date")[:11]
    pinned_article = Articles.objects.get(pinned=True)

    # 序列化数据
    pinned_data = ArticlesSerializer(pinned_article)
    horizontal_data = ArticlesSerializer(data[:3], many=True)
    small_data = ArticlesSerializer(data[3:8], many=True)
    card_data = ArticlesSerializer(data[8:], many=True)

    final_data = {
        "pinned":pinned_data.data,
        "horizontal": horizontal_data.data,
        "small": small_data.data,
        "card": card_data.data
    }

ModelViewSet示例代码

class ArticleGridList(viewsets.ModelViewSet):
    queryset = Articles.objects.all().order_by("-created_date")
    serializer_class = ArticlesSerializer

应用urls.py配置

router = routers.SimpleRouter()
router.register('articles', ArticlesViewSet)
urlpatterns = [
  path("article-grid-list/", article_grid_list)
] + static(settings.MEDIA_URL, document_root=settings.MEDIA_ROOT)

urlpatterns += router.urls

解决方法

方法1:序列化时传入request上下文

Django REST Framework的序列化器支持通过context参数接收request对象,传入后ImageField会自动生成带主机名的完整URL。只需修改函数视图中的序列化代码:

@api_view(["GET"])
def article_grid_list(request):
    data = Articles.objects.all().order_by("-created_date")[:11]
    pinned_article = Articles.objects.get(pinned=True)

    # 给序列化器传入包含request的context
    pinned_data = ArticlesSerializer(pinned_article, context={'request': request})
    horizontal_data = ArticlesSerializer(data[:3], many=True, context={'request': request})
    small_data = ArticlesSerializer(data[3:8], many=True, context={'request': request})
    card_data = ArticlesSerializer(data[8:], many=True, context={'request': request})

    final_data = {
        "pinned": pinned_data.data,
        "horizontal": horizontal_data.data,
        "small": small_data.data,
        "card": card_data.data
    }
    return Response(final_data)  # 注意要返回Response对象

方法2:自定义序列化器字段(灵活扩展用)

如果需要对URL生成逻辑做自定义控制,可以在序列化器中重写cover字段,手动拼接完整URL:

from rest_framework import serializers

class ArticlesSerializer(serializers.ModelSerializer):
    cover = serializers.SerializerMethodField()

    def get_cover(self, obj):
        if obj.cover:
            # 从context中获取request,生成完整URL
            request = self.context.get('request')
            return request.build_absolute_uri(obj.cover.url)
        return None

    class Meta:
        model = Articles
        fields = ['cover', 'title', 'created_date']  # 替换为你的实际字段

注意:使用该方法时,同样需要在函数视图序列化时传入context={'request': request},和方法1配合生效。


原理说明

ModelViewSet之所以能自动生成完整URL,是因为它在处理请求时会自动将request对象传入序列化器的context中,而函数视图需要手动传递这个参数,让序列化器能获取到当前请求的主机信息,从而生成完整URL。

内容的提问来源于stack exchange,提问作者Hasan Vajdi

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.11 11:40:36