45

Variations of this question have been asked, but I'm still unable to get my stylesheets to load correctly when my templates are rendered.

I'm attempting to serve static media from the Django process during development - which is strongly discouraged in production, I'm aware. I'll post my configuration and my template, and hopefully someone can help me to understand where I'm going wrong.

Note that I did try to follow the example on the Django project website, however it doesn't mention how to refer to your stylesheets from a template. I've also tried many different variations of the same thing, so my code/settings may be a little off from what's described.

settings.py

MEDIA_ROOT = 'D:/Dev Tools/django_projects/dso/media'
MEDIA_URL = '/media/'
ADMIN_MEDIA_PREFIX = '/media/'

urls.py

from django.conf.urls.defaults import *
from django.conf import settings
from django.contrib import admin

admin.autodiscover()

urlpatterns = patterns('',
    (r'^admin/(.*)', admin.site.root),
    (r'^ovramt/$', 'dso.ovramt.views.index'),
)

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

Within my template:

<head> 
<title> {% block title %} DSO Template {% endblock %} </title> 
<meta http-equiv="Content-Type" content="text/html;charset=utf-8" >
<link rel="stylesheet" type="text/css" href="../media/styles.css">
</head>

I assure you, the files (templates/media) are in the correct directory on my file system. If there's any extra information I need to provide, please post a comment.


Edit:

One of the problems I was having was the use of a '/' prepending my links. If the forward slash is prepended, the link is opened from the root of the site. If there is no forward slash, the link is opened in the current level. An example:

www.example.com/application/ has a link "/app2/ and a link "app3/".
app2 will open at www.example.com/app2/ and app3 will open at www.example.com/application/app3/. This was confusing me I think.

Josh Smeaton
  • 47,939
  • 24
  • 129
  • 164
  • 1
    One question; have you tried loading "http:///media/styles.css" directly from your browser? – muhuk Jan 15 '09 at 08:49
  • 3
    I am the only one who finds it silly that you have to jump through all these hoops to test/preview CSS and images during development with Django? Sure, you don't want to do this in production and use a real web server, but for development you need to see styles/images to give a good preview. – Wayne Molina Jan 20 '09 at 15:02
  • 2
    There really weren't many hoops to jump through. I just stumbled where I probably shouldn't have. – Josh Smeaton Jan 21 '09 at 06:55
  • 1
    you said "If the forward slash is prepended, the link is opened from the level below." but actually, a forward slash makes it load from the topmost level. So from site.com/a/b/c, if there is a link to /d, it will go to site.com/d. – fastmultiplication Mar 21 '10 at 04:46

7 Answers7

51

I just had to figure this out myself.

settings.py:

MEDIA_ROOT = 'C:/Server/Projects/project_name/static/'
MEDIA_URL = '/static/'
ADMIN_MEDIA_PREFIX = '/media/'

urls.py:

from django.conf import settings
...
if settings.DEBUG:
    urlpatterns += patterns('',
        (r'^static/(?P<path>.*)$', 'django.views.static.serve', {'document_root': settings.MEDIA_ROOT}),
    )

template file:

<link rel="stylesheet" type="text/css" href="/static/css/style.css" />

With the file located here:

"C:/Server/Projects/project_name/static/css/style.css"
Chris
  • 11,780
  • 13
  • 48
  • 70
Ty.
  • 1,810
  • 2
  • 18
  • 26
  • 5
    MEDIA_URL and the ADMIN_MEDIA_PREFIX; they can be same. It is just not a good idea. – muhuk Jan 17 '09 at 13:45
  • True, because one will always override the other and you'll end up serving your app's media files from the same folder as you're admin's media files. That's just usually not the desired result. – Ty. Jan 19 '09 at 18:55
  • why is the url under "settings.DEBUG"? will it work if you aren't in debug mode? – anc1revv Jul 16 '12 at 03:56
  • I used it as the conditional because it's not something you want enabled in production, and generally the DEBUG setting is only enabled while developing locally. You should have your production web server configured to serve static files without passing them to Django. – Ty. Sep 16 '13 at 20:55
11

Django already has a context process for MEDIA_URL, see Django's documentation.

It should be availbale by default (unless you've customized CONTEXT_PROCESSORS and forgot to add it) in a RequestContext.

  • 3
    For Example: You can also follow this bit to ease your development locally: http://docs.djangoproject.com/en/1.0/howto/static-files/ – edmundito Jun 04 '09 at 21:52
6

I usually make my own Template simple tag because Django isn't giving CSS/JavaScript files. Apache does it so my media url is usually http://static.mysite.com.

yourApp/templatetags/media_url.py:

from django.template import Library
from yourapp.settings import MEDIA_URL
register = Library()

@register.simple_tag
def media_url():
    return MEDIA_URL

And in my template file:

{% load media_url %}
<link href="{{ media_url }}css/main.css" rel="stylesheet" type="text/css">

You could also make your own context preprocessor to add the media_url variable in every template.

Community
  • 1
  • 1
bchhun
  • 18,116
  • 8
  • 28
  • 31
2

I just use absolute naming. Unless you're running the site in a deep path (or even if you are), I'd drop the .. and go for something like:

<link rel="stylesheet" type="text/css" href="/media/styles.css">
Oli
  • 235,628
  • 64
  • 220
  • 299
1

I've got a couple of ideas, I don't know which one of them is working for me :)

Make sure to use a trailing slash, and to have this be different from the MEDIA_URL setting (since the same URL cannot be mapped onto two different sets of files).

That's from http://docs.djangoproject.com/en/dev/ref/settings/#admin-media-prefix

Secondly, it may be that you're confusing directories on your filesystem with url paths. Try using absolute urls, and then refine them down.

sykora
  • 96,888
  • 11
  • 64
  • 71
1

Just thought I'd chime in quickly. While all the propositions here work just fine, and I do use Ty's example while developing, once you hit production you might want to opt to serve files via a straight Apache, or whichever else server you're using.

What I do is I setup a subdomain once I'm done developing, and replace all links to static media. For instance:

<link rel="stylesheet" type="text/css" href="http://static.mydomain.com/css/style.css" />

The reasons for doing this are two-fold. First, it just seems like it would be slower to have Django handle these requests when it's not needed. Second, since most browsers can actually download files simultaneously from 3 different domains, using a second sub-domain for your static files will actually speed up the download speed of your users.

David
  • 3,226
  • 3
  • 23
  • 18
0

Another thing to add is that if you have a separate media server on a subdomain/different domain, you can disable cookies for your static media. Saves a little processing and bandwidth.

datashaman
  • 8,301
  • 3
  • 22
  • 29