your folder structure. This issue seems especially pertinent for Django
because although the mechanism for assembling several apps together on
one server is a sweet way to make it easy to combine and reconfigure
applications, having to specify a single global MEDIA_ROOT/MEDIA_URL
kind of limits it. You can't just put static files in the same
directory as the template files, like JSP developers (for instance)
often do. It'd be convenient if each app had "media" subdirectory or
something to go with its models, views, and templates. And actually,
the admin app is an excellent example of this! But admin has to have
its own special setting (ADMIN_MEDIA_PREFIX) and handler to make it
work. Is there any suggested strategy for how other apps can have their
own media directories too? What's the common practice?
<Location "static">
SetHandler None
</Location>
This is the exact approach that I use, but it doesn't avoid the issue
that Greg is talking about. That is; a series of static-file URLs are
likely to be associated with any given application, and the path to them
isn't necessarily going to be the same for each installation of that
application (because, amongst other reasons, there are many different
ways they could be deployed - as you've just shown).
Personally, I'm happy using root-relative URLs for the moment. The
resulting directory structure isn't overly complicated, so could be
easily replicated. However, I can think of a couple of approaches to
ease the problem:
1) Make it a standards that your apps will have all their media in
/static/appname/. This isn't hard to do, and produces an easily portable
directory tree. Root-relative (or absolute) again, though.
2) Create all your templates so that static media urls look like
"{{base_url}}/image.png". Define a constant at the top of the file
defining your views, and store the appropriate base URL in it. Pass this
constant into your template renderer. This means that where you are
storing your static files is only hardcoded once, and can easily be changed.
In fact, I think I've seen a couple of people write function decorators
and other nifty tricks specifically to do things like render templates
with additional variables... just a thought.
The problem with both of these approaches is that if you're
using an app (or several) that you haven't written yourself, they won't
necessarily follow this standard, and could conflict.
-Andy
I started writing something more like Andy's #2 suggestion... a way to
abstract the media root so it doesn't have to be hardcoded all over my
templates. I made a tag to generate static URLs, and hacked the django
code in order to remember a template's application's settings like the
location of the media directory (if the template belongs to a
application, that is). It works really well but I imagine there are
various kinds of issues to consider for a facility like that. And
you're right Andy, it's not really a ideal solution unless all the apps
you're using use it. Well, it sounds like the dev team has their hands
full right now with more important things like magic-removal and 1.0,
but maybe I'll float this idea after that. Mostly I just wanted to make
sure I wasn't high or completely missing the point.
My specific problem is that I have a bunch of sites in development on
my laptop:
http://localhost/coolsite/
http://localhost/boringsite/
http://localhost/newhomepage/
And these then get deployed to production servers:
http://coolsite.com/
http://boringsite/newcoolthing/
http://homepage.org/
I solve it right now by adding a setting, URLBASE, and then doing
circles to get it into everything, mainly with lots of extra_context
stuff to push it through generic views into templates.
I'm aware this is sub-optimal.
One solution is to use the sites functionality - will Django bork if
my site url is localhost/folder?
The other is to use a middleware or context processor to pull in
URLBASE.
Ben
________________________________
Afternoon, man about the Internet -- http://aftnn.org/
In settings, I add whatever custom variables I want, including this:
APP_BASE = "http://www.example.com/"
I have an app called home, and in the views.py I put this:
---
"""
A request processor that returns dictionary to be merged into a
template context. Function takes the request object as its only
parameter
and returns a dictionary to add to the context.
These are referenced from the setting TEMPLATE_CONTEXT_PROCESSORS and
used by DjangoContext.
"""
from django.conf.settings import APP_BASE
def set_vars(request):
"""
Returns custom context variables required by this app from
settings.py
"""
context_extras = {}
context_extras['APP_BASE'] = APP_BASE
return context_extras
---------
You could add other custom variables to this.
In settings again, I added to...
TEMPLATE_CONTEXT_PROCESSORS = (
...
"django.models.home.set_vars",
)
In the template use
<a href="{{ APP_BASE }}thing/somethingelse/">...
The one gotcha with this is you must remember to use DjangoContext in
your views:
from django.core.extensions import DjangoContext as Context
But then you have to do that to use any of the template context
processors.
Derek
Well, if all of your sites are separate django projects that's easy, you already have a (static) dir pointed by your
MEDIA_URL, so:
1. Store file system path to your project in the SITE_ROOT variable in the config file.
2. Anywhere when you must supply a path (like ImageField, MEDIA_ROOT, etc.), use os.path.join(SITE_ROOT, 'foo').
3. Put all of your static files under /media/ and always use URLs like this /media/img/foo.png, /media/js/foo.js, etc.
4. Setup URLs:
- Config file:
ADMIN_MEDIA_PREFIX = '/admin-media/'
MEDIA_URL = os.path.join(SITE_ROOT, 'media')
MEDIA_PREFIX = '/media/'
- Apache:
Alias /media/ "<SITE_ROOT>/media/"
Alias /admin-media/ "<django root>/django/contrib/admin/media/"
- Lighttpd:
alias.url = (
"/media/" => "<SITE_ROOT>/media/",
"/admin-media/" => "<django root>/django/contrib/admin/media/",
)
5. Also you can use this in your main url conf to make this files accessible when using django-admin.py runserver (from
another post on the list) - admin media files are handled automagically:
from django.conf.settings import LOCAL_DEV, SITE_ROOT
if LOCAL_DEV:
import os
urlpatterns += patterns('',
(r'^media/(?P<path>.*)$', 'django.views.static.serve', {'document_root': os.path.join(SITE_ROOT, 'media')}),
)
#
I'm using a LOCAL_DEV var to distinguish between local runserver (DEBUG=LOCAL_DEV=True), staging server (DEBUG=True,
LOCAL_DEV=False) and production server (DEBUG=LOCAL_DEV=False).
With this setting I have a local server, a staging server and a production server setup which only differs in SITE_ROOT
(sometimes, because I tend to replicate directory structure from my production server), LOCAL_DEV and DEBUG variables.
--
Nebojša Đorđević - nesh
Studio Quattro - Niš - SCG
http://studioquattro.biz/forum/
http://djnesh.blogspot.com/ | http://djnesh-django.blogspot.com/ |
http://djangoutils.python-hosting.com/
Registered Linux User 282159 [http://counter.li.org]
MEDIA_URL = URLBASE + "/media/"
Something like Rails' routing would be really interesting for me, but
I confess I don't really know much about their solution, or what
would be a good fit here.
On 19 Jan 2006, at 19:05, Nebojša Đorđević wrote:
> Well, if all of your sites are separate django projects that's
> easy, you already have a (static) dir pointed by your
> MEDIA_URL, so:
Yes, I also hit the same problem, but because I have control of my DNS, I use sub domains for stuff like that. So
http://boringsite/newcoolthing/ becomes http://newcoolthing.boringsite/.
Dev Site
localhost/mysite/images/whatever.gif
Production
mysite.com/images/whatever.gif
And even the occasional development on my laptop on the road
localhost/~myuser/mysite/images/whatever.gif
This was never a problem in my previous dev environment (php) because
I'd always just use relative urls like:
<img src="images/whatever.gif">
But with django's more flexible url mapping, I need to make all the
links absolute.
The most frequent suggestion is just to define a setting such as the
MEDIA_ROOT that can be set to "/images" on my production server,
"/mysite/images" on my dev and then "~myuser/mysite/images" on the
laptop example.
Looking at ruby on rails, they seem to have some template tag
equivalent that does url generation for you automatically (stolen from
the rails tutorial):
<%= link_to recipe.title.....
Perhaps django could use something similar?