Django Admin媒体前缀URL问题

7 投票
2 回答
24203 浏览
提问于 2025-04-16 12:43

我有以下的文件夹结构

src\BAT\templates\admin\base.html
src\BAT\media\base.css
src\BAT\media\admin-media\base.css

settings.py

MEDIA_ROOT = os.path.join( APP_DIR, 'media' )
MEDIA_URL = '/media/'
ADMIN_MEDIA_PREFIX = '/admin-media/'
TEMPLATE_DIRS = (
    os.path.join( APP_DIR, 'templates' )
)
INSTALLED_APPS = (
    'django.contrib.auth',
    'django.contrib.contenttypes',
    'django.contrib.sessions',
    'django.contrib.sites',
    'django.contrib.messages',
    'django.contrib.admin',
    'django.contrib.admindocs',
)

urls.py

urlpatterns = patterns('',
    (r'^admin/doc/', include('django.contrib.admindocs.urls')),

    (r'^admin/', include(admin.site.urls)),

    (r'^media/(?P<path>.*)$', 'django.views.static.serve', {'document_root': settings.MEDIA_ROOT}),

)

我需要在我的应用中获取两个CSS文件。我的base.html文件包含了

<head>
<title>{% block title %}{% endblock %}</title>
<link href="{{ MEDIA_URL }}css/base.css" rel="stylesheet" type="text/css" />
<link href="{{ MEDIA_URL }}{{ADMIN_MEDIA_PREFIX}}css/base.css" rel="stylesheet" type="text/css" />
<link rel="stylesheet" type="text/css" href="{% block stylesheet %}{% load adminmedia %}{% admin_media_prefix %}css/base.css{% endblock %}" />
{% block extrastyle %}{% endblock %}
<!--[if lte IE 7]><link rel="stylesheet" type="text/css" href="{% block stylesheet_ie %}{% load adminmedia %}{% admin_media_prefix %}css/ie.css{% endblock %}" /><![endif]-->
{% if LANGUAGE_BIDI %}<link rel="stylesheet" type="text/css" href="{% block stylesheet_rtl %}{% admin_media_prefix %}css/rtl.css{% endblock %}" />{% endif %}
<script type="text/javascript">window.__admin_media_prefix__ = "{% filter escapejs %}{% admin_media_prefix %}{% endfilter %}";</script>
{% block extrahead %}{% endblock %}
{% block blockbots %}<meta name="robots" content="NONE,NOARCHIVE" />{% endblock %}
</head>

我想在这个网址 http://localhost:8000/admin 得到以下输出

<head>
<title>Site administration | My site admin</title>
<link href="/media/css/base.css" rel="stylesheet" type="text/css" />
<link href="/media/admin-media/css/base.css" rel="stylesheet" type="text/css" />
<link rel="stylesheet" type="text/css" href="/media/admin/css/base.css" />
<link rel="stylesheet" type="text/css" href="/media/admin/css/dashboard.css" />

但是我总是得到

<head>
<title>Site administration | My site admin</title>
<link href="/media/css/base.css" rel="stylesheet" type="text/css" />
<link href="/media/css/base.css" rel="stylesheet" type="text/css" />
<link rel="stylesheet" type="text/css" href="/admin-media/css/base.css" />
<link rel="stylesheet" type="text/css" href="/admin-media/css/dashboard.css" />

当我直接访问 http://localhost:8000/admin-media/css/base.css 时,显示的是来自Python的包文件夹中的django/contrib/admin/media/css的CSS文件。

而直接访问 http://localhost:8000/media/admin-media/css/base.css 时,显示的是来自src/media/admin-media/css/的CSS文件。

再者,直接访问 http://localhost:8000/media/css/base.css 时,显示的是来自src/media/css/的CSS文件。

2 个回答

3

Django 1.4 引入了一种新的方式来加载静态媒体文件。如果你在使用这个版本,建议你看看这个链接:https://docs.djangoproject.com/en/dev/howto/static-files/

简单来说,上面链接的内容是说,现在有两个新的设置变量,分别是 STATIC_URL 和 STATIC_ROOT。它们和一个新加的应用(django.contrib.staticfiles)一起使用,用来收集和提供静态文件,这些文件是按应用来管理的。

在我升级 Django 的时候,我需要把我的 STATIC_ROOT 设置成之前的 MEDIA_URL。

在这个新系统下,模板现在应该使用 {{ STATIC_URL }}。

10

对于Django 1.4及更新版本来说,这一点很重要(可以查看这里):

从Django 1.4开始,管理界面的静态文件也遵循这个新规则,这样可以更方便地部署这些文件。在之前的Django版本中,通常会定义一个叫做ADMIN_MEDIA_PREFIX的设置,用来指向管理界面静态文件在网络服务器上的URL。现在这个设置已经被淘汰,取而代之的是一个更通用的设置叫做STATIC_URL。Django现在会期待在URL <STATIC_URL>/admin/ 下找到管理界面的静态文件。


之前的回答,适用于旧版Django:

ADMIN_MEDIA_PREFIX是一个绝对的URL前缀,它和MEDIA_URL没有关系——这两个可以指向完全不同的地方。确实,名字中的“_PREFIX”这个选择有点误导。

所以,应该用{% admin_media_prefix %}css/base.css,而不是{{ MEDIA_URL }}{{ADMIN_MEDIA_PREFIX}}css/base.css。然后你需要确保网络服务器能在'/admin-media/'这个路径下提供管理界面的媒体文件。

注意,我在上面使用了admin_media_prefix这个标签,它需要在模板的开头加上{% load adminmedia %}。而普通的媒体上下文处理器只会给你提供MEDIA_URL这个变量,遗憾的是。

为了覆盖默认的管理媒体文件提供方式,可以在你的URL配置中尝试类似这样的设置:

# A handy helper function I always use for site-relative paths
def fromRelativePath(*relativeComponents):
    return os.path.join(os.path.dirname(__file__), *relativeComponents).replace("\\","/")

[...]

url("^admin-media/(?P<path>.*)$",
    "django.views.static.serve",
    {"document_root": fromRelativePath("media", "admin-media")})

撰写回答