Opened 10 years ago

Closed 10 years ago

Last modified 9 years ago

#119 closed enhancement (wontfix)

Serving media

Reported by: brantley (deadwisdom@… Owned by: adrian
Component: Core (Other) Version:
Severity: normal Keywords: media wsgi images
Cc: Triage Stage: Unreviewed
Has patch: no Needs documentation: no
Needs tests: no Patch needs improvement: no
Easy pickings: UI/UX:

Description

There is currently no way of serving media through Django, which might be alright for mod_python as it's counting on Apache, but the WSGI server doesn't have such benefits.

Change History (15)

comment:1 Changed 10 years ago by adrian

  • Resolution set to wontfix
  • Status changed from new to closed

Django isn't intended to serve media. It's your responsibility to serve them via a method of your choosing. I'd recommend lighttpd or a trimmed-down version of Apache.

comment:2 Changed 10 years ago by SImon Willison

  • Resolution wontfix deleted
  • Status changed from closed to reopened

I think we should document that mod_python trick we used to use (still use?) where you tun off mod_python handling for a certain path - /m/ for example - to allow media to be served from the corresponding location on the file system. Sure it's better to run a separate stripped down web server but for people who don't mine having mod_python instances serving up images that trick will save them running more than one web server.

comment:3 Changed 10 years ago by adrian

  • Resolution set to fixed
  • Status changed from reopened to closed

Fixed in [260]. Added 'Serving media files' to docs/modpython.txt.

comment:4 Changed 10 years ago by ian maurer

  • priority changed from normal to lowest
  • Resolution fixed deleted
  • Severity changed from normal to enhancement
  • Status changed from closed to reopened

Sorry to re-open this on you...

I spent too much time trying to get mod_python to work on my Windows dev machine with no luck. Getting it setup on linux is a piece of cake, but it appears that Windows setup is an afterthought for the mod_python team (which is understandable, but its frustrating to me).

Any chance we can add a global setting called ADMIN_MEDIA_ROOT to go along with ADMIN_MEDIA_PREFIX? This would allow people to leverage the AdminMediaHandler if they desire, to make delivering of image and css files thru djanog possible.

I set this up on my local machine and would like to see it folded into the project. If not, I can just create my own MediaHandler class in my project and create my own runner function.

Inside of the basehttp.py file we could then allow the overriding of the admin_media directory:

class AdminMediaHandler:
    def __init__(self, application):
...
        if settings.ADMIN_MEDIA_ROOT:
            self.media_dir = settings.ADMIN_MEDIA_ROOT
        else:
            self.media_dir = django.__path__[0] + '/conf/admin_media'
        self.media_url = settings.ADMIN_MEDIA_PREFIX


Then in global_settings.py,

# URL prefix for admin media -- CSS, JavaScript and images. Make sure to use a
# trailing slash.
# Examples: "http://foo.com/media/", "/media/".
ADMIN_MEDIA_PREFIX = '/media/'

# Absolute path to the directory that holds admin media.
ADMIN_MEDIA_ROOT = None

comment:5 Changed 10 years ago by adrian

  • Resolution set to wontfix
  • Status changed from reopened to closed

Django isn't intended to serve media. It's your responsibility to serve them via a method of your choosing. I'd recommend lighttpd or a trimmed-down version of Apache.

comment:6 Changed 10 years ago by hugo <gb@…>

Just as a side note: if one is so inclined, one could use my filebrowser sample to deliver media directly with django. It might not be a good idea on production systems (although there _might_ be situations where media are better served by django, for example to control access with django permissions), but it might help people with development: you just need django running and would add your media roots to the filesystem list and could serve stuff from there directly.

comment:7 Changed 10 years ago by kkennedy@…

Just a comment. I have to throw my $0.02 in with Ian here, and his suggestion to add ADMIN_MEDIA_ROOT. Of course the framework isn't intended to serve media...but you're gotten a lot of new fans recently, and we LOVE the up-and-running fast nature of the project. I realize you don't see a big deal in just running a separate apache and/or lighttpd server to serve media. But when I'm trying to get a little mini dev environment going on my laptop, in a plane, why make me bother with that just to serve up my CSS files for rendering? Sure, peformance will suck, but it's the basehttp server anyway! All I really need is to be able to override the conf/admin_media (as Ian solves above perfectly), so that I can serve up the files. (I've already patched basehttp...thanks for the idea, Ian!)

Does that make sense? I know it's a different problem space than you may be used to, but it's real. A buddy of mine and I that both got this up and running this week have been ranting over this in IM for an hour now...*grin*. Throw a guy a bone!

By the way...this framework ROCKS. Regardless, I'm not going anywhere. I love it!

comment:8 Changed 10 years ago by Ken Kennedy <kkennedy@…>

Correction. I'm actually using:

try:
    from django.conf.settings import ADMIN_MEDIA_PREFIX
    self.media_dir = settings.ADMIN_MEDIA_ROOT
except AttributeError:
    self.media_dir = django.__path__[0] + '/conf/admin_media'

and setting a custom ADMIN_MEDIA_ROOT in myproject.settings.main

It's a hack, but it's easy to understand, and it seems to work.

comment:9 Changed 10 years ago by Ken Kennedy <kkennedy@…>

Frack. That change seems to be shared by both my admin and "main" sites, when in development mode. So my admin CSS gets changed as well, which sucks. Dang. I think I'd rather work on my site stuff right now, so I'll deal with this later. Oh well!

comment:10 Changed 10 years ago by Ken Kennedy <kkennedy@…>

Ugh. I've been up too long or something. How many errors in only 5 lines? *sigh* But now I realize I don't want to use ADMIN_MEDIA_ROOT anyway. You guys definitely know what you're doing...you've seen these requests before, haven't you? *grin*

Thanks for the great framework.

comment:11 Changed 9 years ago by anonymous

Quick and Dirty Workaround for CSS (but works for images too)

Create a directory to contain your media/css/images etc. etc.

create the following view:

from django.utils.httpwrappers import HttpResponse
import os

def media(request, file_name):
	res = HttpResponse()
	path = os.path.join('/path/to/your/media/dir/', file_name)
	f = open(path, 'rb')

	res.write(f.read())
	res['Content-Type'] = 'text/css'

	return res

Then add this to your urls.py

(r'^media/(?P<file_name>\S+)', 'dotted.notation.to.your.view.media'),

you can then access your media under /media/* in your browser.
Subdirectories work too (e.g. /media/css/mystyle.css)

WARNING! This is very insecure as the filename is not sanitized in any way.

I need it for CSS but most browsers dont care if you deliver an image as text/css.

Be sure to remove this before you deploy your app.

comment:12 Changed 9 years ago by anonymous

Thanks for that bit of view code there. It's a great help for setting up a rapid dev enviroment, although far from a perfect solution as you mention.

It's extremely frustrating that the base http server (which isn't meant for production anyway) won't just stream bytes for media. It's even more frustrating that an exception is made for the admin app. As a neophyte, I spent an inordinate amount of time trying to figure that out until someone on IRC kindly explained the situation to me. Anyway, it seem trac doesn't have a voting feature, so please consider this comment as my support for the issue.

comment:13 Changed 9 years ago by GrumpySimon

You could probably just run a SimpleHTTPServer instance to serve media files in your dev. environment, and just reference localhost:<alt. port> (i.e. 8080 here ) for your media.

e.g.

# From http://effbot.org/librarybook/simplehttpserver.htm

import SimpleHTTPServer
import SocketServer

# minimal web server.  serves files relative to the
# current directory.

PORT = 8080

Handler = SimpleHTTPServer.SimpleHTTPRequestHandler

httpd = SocketServer.TCPServer(("", PORT), Handler)

print "serving at port", PORT
httpd.serve_forever()

comment:14 Changed 9 years ago by anonymous

I'll have to give that a try. Thanks for the info. It's still a workaround for something that should be fixed natively though I think. In talking on IRC, I'm apparently not the only one that spent an inordinate amount of time trying to figure out why the admin app can do it but user apps cannot. Additionally, asking someone to set all this up to serve CSS files, yet explaining to him that you can start developing with django in no time is a bit disingenuous.

comment:15 Changed 9 years ago by hugo

There is a solution in core: just use the django.views.static.serve view function. Look at the source for documentation.

Note: See TracTickets for help on using tickets.
Back to Top