7

i 've the following folder structure

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}),

)

I need to get both the CSS files in my application. my base.html contains

<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>

I want to get the following output for URL 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" />

But I always getting

<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" />

while direct accessing http://localhost:8000/admin-media/css/base.css shows css file from Python site-packages/django/contrib/admin/media/css

while direct accessing http://localhost:8000/media/admin-media/css/base.css shows css file from src/media/admin-media/css/

while direct accessing http://localhost:8000/media/css/base.css shows css file from src/media/css/

Mithun Sreedharan
  • 49,883
  • 70
  • 181
  • 236

2 Answers2

10

Important for Django 1.4 and newer (see here):

Starting in Django 1.4, the admin’s static files also follow this convention, to make the files easier to deploy. In previous versions of Django, it was also common to define an ADMIN_MEDIA_PREFIX setting to point to the URL where the admin’s static files live on a Web server. This setting has now been deprecated and replaced by the more general setting STATIC_URL. Django will now expect to find the admin static files under the URL <STATIC_URL>/admin/.


Previous answer, for older Django releases:

ADMIN_MEDIA_PREFIX is meant to be an absolute URL prefix, it has nothing to do with the MEDIA_URL - both can point to completely different points. Admittedly, the (bad) choice of "_PREFIX" in the name somewhat suggests that.

So, instead of {{ MEDIA_URL }}{{ADMIN_MEDIA_PREFIX}}css/base.css it must be {% admin_media_prefix %}css/base.css. And then you have to ensure that the web server serves the admin media files on '/admin-media/'.

Note that I used the admin_media_prefix tag above, which needs {% load adminmedia %} at the beginning of the template. The regular media context processor only gives you the MEDIA_URL variable, unfortunately.

In order to override the vanilla admin media serving, try something like this in your URLconf:

# 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")})
AndiDog
  • 68,631
  • 21
  • 159
  • 205
  • Do i need to add something on urls.py to ensure to ensure that the web server serves the admin media files on '/admin-media/'? Please see last part of my question; which css files get output while directly accessing the URLs – Mithun Sreedharan Mar 01 '11 at 08:41
  • 1
    @Mithun: Edited my answer. You don't have a ADMIN_MEDIA_PREFIX variable available in templates with the media context processor. And another hint: If you had something like `TEMPLATE_STRING_IF_INVALID = "(invalid variable '%s'!)" if DEBUG else ""` in your settings, you would have noticed this. – AndiDog Mar 01 '11 at 08:41
  • @Mithun: Well I thought you wanted to serve the vanilla admin files?! If not you need to override the '/admin-media/' URL with your own directory. – AndiDog Mar 01 '11 at 08:43
  • `` yelds `` which is from site-packages/django/contrib/admin/media/css. But `` yelds `` from src/media/admin-media/css/ (What I want!!) – Mithun Sreedharan Mar 01 '11 at 08:49
  • @AndiDog, Yea I don't want default css comes with Django admin, I'm trying to override it with my own custom admin css file. – Mithun Sreedharan Mar 01 '11 at 08:55
  • @Mithun: Ad "What I Want!!" - that is pure coincidence because you have the "media/admin-media" folder structure. Use *either* MEDIA_URL *or* admin_media_prefix! So if you want to want to serve "media/admin-media" as admin media, why not just change `settings.ADMIN_MEDIA_PREFIX` to '/media/admin-media/'? But I'm not quite suire whether the admin app overwrites this URL, please try it out. – AndiDog Mar 01 '11 at 08:55
  • @AndiDog, Issue is that setting `ADMIN_MEDIA_PREFIX = '/media/admin-media/'` makes `http://localhost:8000/media/admin-media/css/base.css` load from site-packages/django/contrib/admin/media/css folder – Mithun Sreedharan Mar 01 '11 at 09:02
  • 1
    @Mithun: OMG it took me 10 minutes to find out how admin serves its media files. Hint: `staticfiles.finders.AppDirectoriesFinder` looks for the "media" directory in each app, including the admin app. I'll edit my answer to include an example to override that (hopefully that won't get overwritten by `AppDirectoriesFinder`). – AndiDog Mar 01 '11 at 09:29
  • ADMIN_MEDIA_PREFIX is deprecated. – dan-klasson Apr 10 '13 at 14:14
3

Django 1.4 uses a new strategy for loading static media files, those using it will want to read over https://docs.djangoproject.com/en/dev/howto/static-files/

The executive summary of the above link is that two new settings variables, STATIC_URL and STATIC_ROOT, are used together with a newly included app (django.contrib.staticfiles) to collect and serve static files which are included on a per app basis.

When upgrading my django installation I had to set my STATIC_ROOT equal to my previous MEDIA_URL.

Under this system templates should now use {{ STATIC_URL }}.

tjb
  • 11,480
  • 9
  • 70
  • 91