I'm relatively new to Django (1.4) and I'm having a hard time understanding the philosophy behind static, media, and admin files. The structure of the project is different from one tutorial to another, and same thing for Webfaction(where I'll be hosting my application). I would like to know what is the optimal way to organize it and with least pain and editing while deploying it to Webfaction, what is the point of static media, adn admin files?
Thank you in advance
In essence you want to serve static files by django in development. Once you're ready to go into production you want the server to do this for you (they are build to do it fast :-))
Here's a basic setup, once you login the server you run the collectstatic command to get all the staticfiles in the static-root folder, which your server points to (see the rewrite rules)
./manage.py collectstatic
settings.py
from os import path
import socket
PROJECT_ROOT = path.dirname(path.abspath(__file__)) #gets directory settings is in
# Dynamic content is saved to here
MEDIA_ROOT = path.join(PROJECT_ROOT,'media')
# if ".webfaction.com" in socket.gethostname():
# MEDIA_URL = 'http://(dev.)yourdomain.com/media/'
# else:
MEDIA_URL = '/media/'
# Static content is saved to here --
STATIC_ROOT = path.join(PROJECT_ROOT,'static-root') # this folder is used to collect static files in production. not used in development
STATIC_URL = "/static/"
STATICFILES_DIRS = (
('', path.join(PROJECT_ROOT,'static')), #store site-specific media here.
)
# List of finder classes that know how to find static files in
# various locations.
STATICFILES_FINDERS = (
'django.contrib.staticfiles.finders.FileSystemFinder',
'django.contrib.staticfiles.finders.AppDirectoriesFinder',
# 'django.contrib.staticfiles.finders.DefaultStorageFinder',
)
settings_deployment.py
from settings import *
DEBUG = False
TEMPLATE_DEBUG = DEBUG
MEDIA_URL = "http://yourdomain.com/media/"
urls.py
...other url patterns...
if settings.DEBUG:
urlpatterns += staticfiles_urlpatterns() #this serves static files and media files.
#in case media is not served correctly
urlpatterns += patterns('',
url(r'^media/(?P<path>.*)$', 'django.views.static.serve', {
'document_root': settings.MEDIA_ROOT,
}),
)
django.conf (lighttpd, this could be apache or nginx) but I believe webfaction has an app service to set this up easily
$HTTP["host"] =~ "(^|\.)yourdomain\.com$" {
fastcgi.server = (
"/django.fcgi" => (
"main" => (
"socket" => env.HOME + "/project/project.sock",
"check-local" => "disable",
)
),
)
alias.url = (
"/media" => env.HOME + "/project/media",
"/static" => env.HOME + "/project/static-root",
)
url.rewrite-once = (
"^(/media.*)$" => "$1",
"^(/static.*)$" => "$1",
"^/favicon\.ico$" => "/static/img/favicon.png",
"^(/.*)$" => "/django.fcgi$1",
)
}
Static files are files needed by your applications that server can serve without modifications, like custom JS scripts, icons, applets, etc. The best way to use it is to place static files in a "static" folder in each of your app's folder. Like this, the test server will find them there, and if you deploy on a production server, you'll just have to run python manage.py collectstatic to copy them all in the root static folder defined in you settings.py
Media files are those uploaded by the users of your applications, like avatar's pics, etc.
Admin files are static files used by Django admin, django test server will just find them, but on production, you'll have to copy or link to this folder for the admin to actually work.
Hope it helps you see things better...
My config is:
1.settings.py
# Absolute filesystem path to the directory that will hold user-uploaded files.
# Example: "/var/www/example.com/media/"
MEDIA_ROOT='/media/'
# URL that handles the media served from MEDIA_ROOT. Make sure to use a
# trailing slash.
# Examples: "http://example.com/media/", "http://media.example.com/"
MEDIA_URL = '/media/'
# Absolute path to the directory static files should be collected to.
# Don't put anything in this directory yourself; store your static files
# in apps' "static/" subdirectories and in STATICFILES_DIRS.
# Example: "/var/www/example.com/static/"
STATIC_ROOT = '/static/'
# URL prefix for static files.
# Example: "http://example.com/static/", "http://static.example.com/"
STATIC_URL = '/static/'
# Additional locations of static files
STATICFILES_DIRS = (
'/'.join(__file__.split(os.sep)[0:-2]+['static']),
# Put strings here, like "/home/html/static" or "C:/www/django/static".
# Always use forward slashes, even on Windows.
# Don't forget to use absolute paths, not relative paths.
)
# List of finder classes that know how to find static files in
# various locations.
STATICFILES_FINDERS = (
'django.contrib.staticfiles.finders.FileSystemFinder',
'django.contrib.staticfiles.finders.AppDirectoriesFinder',
# 'django.contrib.staticfiles.finders.DefaultStorageFinder',
)
2.urls.py
from django.conf import settings
if settings.DEBUG:
from django.contrib.staticfiles.urls import staticfiles_urlpatterns
urlpatterns += staticfiles_urlpatterns()
AND my site dir is like this:
root
│ manage.py
│
├─media
├─my_django_py3
│ settings.py
│ urls.py
│ views.py
│ wsgi.py
│ __init__.py
│
├─static
│ 9gq05.jpg
│ ajax.js
│ favicon.gif
│
├─templates
└─utils
Related
I have developed an application in Python with Django, and I just deployed it on heroku servers.
My settings.py file has this content:
PROJECT_PATH = os.path.dirname(os.path.abspath(__file__))
STATIC_ROOT = 'staticfiles'
STATIC_URL = '/static/'
STATICFILES_DIRS = (
os.path.join(PROJECT_PATH, 'static'),
)
STATICFILES_FINDERS = (
'django.contrib.staticfiles.finders.FileSystemFinder',
'django.contrib.staticfiles.finders.AppDirectoriesFinder',
#'django.contrib.staticfiles.finders.DefaultStorageFinder',
)
when I run this command:
heroku run python manage.py collectstatic --noinput
I get the following error:
OSError: [Errno 2] No such file or directory: '/app/nameOfApp/static'
the urls in templates to the files that were previously stored, such as CSS and javascript files which have this kind of url in the template files:
<script type="text/javascript" src="{% static "javascripts/jquery.min.js" %}" ></script>
are served properly but the new files that are uploaded through admin panels are not stored in the same place as the previous files in static folder, namely the new uploaded files should be stored in the the same folder as other static files such as CSS and javascripts,
Question:
so how should I modify the settings.py file so that it works properly?
Media Root is for Absolute filesystem path to the directory that will hold user-uploaded files.
Example: "/var/www/example.com/media/"
Media URL is for handling the media file served from Media root.
Another important not is you will need to configure these files to be served in both development and production.
by adding this line in urls.py will do the tricks
from django.conf import settings
from django.conf.urls.static import static
urlpatterns = [
# ... the rest of your URLconf goes here ...
] + static(settings.MEDIA_URL, document_root=settings.MEDIA_ROOT)
I've deployed my app on heroku (cedar stack) and all worked fine until a few days ago, When i noticed that my static files are not being served (appear with code 'canceled'). Next thing i noticed is that my project suddenly had new folders on same level as manage.py : admin/, css/, img/ and js/. I didnt create admin at all, using a buildin django admin site and didnt modify it in any way. I did create css, img and js folders under static/ inside my project, and its still there along with all its content. It's like all the folders in static/ got copied to manage.py level.
Running heroku run ls -l shows same changes on heroku. I suspect those changes cause troubles in serving static files.
heroku run python manage.py collectstatic --noinput
shows all files copied no problem.
my static dirs settings:
STATIC_ROOT = ''
STATIC_URL = '/static/'
STATICFILES_DIRS = (
# Put strings here, like "/home/html/static" or "C:/www/django/static".
# Always use forward slashes, even on Windows.
# Don't forget to use absolute paths, not relative paths.
os.path.join(os.path.dirname(__file__), 'static'),
)
STATICFILES_FINDERS = (
'django.contrib.staticfiles.finders.FileSystemFinder',
'django.contrib.staticfiles.finders.AppDirectoriesFinder',
# 'django.contrib.staticfiles.finders.DefaultStorageFinder',
)
I dont use S3 yet.
How to remove those files? What caused those dirs to appear?
When a Django application is deployed to Heroku, collectstatic is automatically run (Heroku docs). This collects all the static assets from your installed apps (including django.contrib.admin) and copies them to the STATIC_ROOT.
Check your STATIC_ROOT setting. It is probably not set correctly.
Here is a tutorial on using S3 with your static files.
Based on this post i learned that all this mess was caused by changing DEBUG to FALSE. Following Ohads' advice i checked my STATIC_ROOT setting, and as you can see, it wasn't set. Those are my fixed settings:
SETTINGS_PATH = os.path.abspath(os.path.dirname(__file__))
STATIC_ROOT = os.path.abspath(SETTINGS_PATH+'/static/')
STATIC_URL = '/static/'
STATICFILES_DIRS = ()
STATICFILES_FINDERS = (
'django.contrib.staticfiles.finders.FileSystemFinder',
'django.contrib.staticfiles.finders.AppDirectoriesFinder',
# 'django.contrib.staticfiles.finders.DefaultStorageFinder',
)
Adding:
if not settings.DEBUG:
urlpatterns += patterns('',
(r'^static/(?P<path>.*)$', 'django.views.static.serve', {'document_root': settings.STATIC_ROOT}),
)
in myapp/urls.py solved my problem.
I'm trying to configure Django to serve static files when using runserver (production works fine). Everything works fine for all of the static files that are under an apps directory. The problem comes with static files that are not under a specific app, but are in the final static directory. For instance, I have this project structure:
/myproject/
/myproject/static/
/myproject/static/css/foo.css
/myproject/app1
/myproject/app1/static/css/bar.css
urls.py
if settings.SERVE_STATIC:
urlpatterns += patterns('',
url(r'^static/(?P<path>.*)$', 'django.views.static.serve',
{'document_root': settings.STATIC_ROOT}),
)
urlpatterns += staticfiles_urlpatterns() # one of these may be redundant.
settings.py
SERVE_STATIC = True
PROJECT_ROOT = '/myproject'
STATIC_ROOT = os.path.join(PROJECT_ROOT, 'static')
STATIC_URL = '/static/'
STATICFILES_DIRS = (os.path.join(PROJECT_ROOT, 'static'),)
INSTALLED_APPS = ('app1',)
With these settings, I get the error:
ImproperlyConfigured: The STATICFILES_DIRS setting should not contain
the STATIC_ROOT setting
Which makes sense. I'm telling Django to collect static files, and put them in the same place - which could cause a loop.
If I comment out the STATICFILES_DIRS variable, django will find the static file 'bar.css'. But it does not find 'foo.css'.
If I comment out the STATIC_ROOT variable and put back the STATICFILES_DIRS, then it finds the file 'foo.css' - but of course, the 'collectstatic' command will no longer work.
Note - I realize that the '/static' directory is supposed to be empty, but the project I'm on, has files there anyway. :) As long as they're not overwritten by 'collectstatic', it looks like Django runserver should serve them - but it doesn't.
How do I serve the static files under STATIC_ROOT (such as foo.css) when running Django runserver?
Move the files that are in /static/ right now to a different directory -- call it /project-static/, for instance.
Then only include this line in urls.py:
urlpatterns += staticfiles_urlpatterns()
(remove the django.views.static.serve view)
And in settings.py, use this:
STATICFILES_DIRS = (os.path.join(PROJECT_ROOT, 'project-static'),)
Then you can put files in /project-static/ directory on your filesystem, the development server will serve them out of the /static/ URL prefix, and in production, collectstatic will find them and put them into the /static/ directory where the web server can find them.
I'm stuck due to an evergreen issue, static files not served. Conversely the files placed in the MEDIA_ROOT subtree get served correctly under MEDIA_URL.
Stripped settings.py:
DEBUG = True
STATIC_URL = '/static/'
STATIC_ROOT = '/home/foo/devel/static'
MEDIA_URL = '/media/'
MEDIA_ROOT = '/home/foo/devel/media'
# the following is deprecated but is it seems grappelly requires it
ADMIN_MEDIA_PREFIX = STATIC_URL + "grappelli/"
STATIC_FILES = ()
STATICFILES_FINDERS = (
'django.contrib.staticfiles.finders.FileSystemFinder',
'django.contrib.staticfiles.finders.AppDirectoriesFinder',
)
To create the project I did:
$ cd /home/foo/devel/
$ virtualenv testdrive
$ . bin/activate; pip install django; cd testdrive
$ django-admin.py fbtest
and got this directory tree (stripped):
. <-- /home/foo/devel/
├── bin
├── fbtest
│ └── fbtest
│ ├── media
│ │ └── foo.jpg
│ ├── static
│ └────── foo.jpg
├── include
└── lib
Files under STATIC_URL should be served automatically by Django staticfiles (not in my case), while other files have to be handled manually. So I appended these lines to urls.py:
import settings
if settings.DEBUG:
urlpatterns += patterns('',
url(r'^%s(?P<path>.*)$' % settings.MEDIA_URL.lstrip("/"),
'django.views.static.serve', {
'document_root': settings.MEDIA_ROOT,
}),
)
Accessing http://host/media/filebrowser/foo.jpg works, while http://host/static/foo.jpg gives error 404. Why?
Files under STATIC_URL should be served automatically by Django staticfiles (not in my case), while other files have to be handled manually.
That's incorrect. Django never serves STATIC_ROOT ever -- not even in development. What it does do is make files in each app's "static" directory and files in any directory specified in STATICFILES_DIRS available at STATIC_URL. You don't actually manually put anything in STATIC_ROOT ever; in fact, in development, you shouldn't even have the directory there. Put simply, STATIC_ROOT is only a dumping ground for your static files in production when you run the collectstatic management command.
In development, all static files should go into someapp/static, where "someapp" is the app they apply to. In the case that the files apply to the project as a whole, a global CSS file for example, you need to create an entirely different directory (i.e. not the same as STATIC_ROOT or MEDIA_ROOT) and then add that directory to STATICFILES_DIRS. For example, I normally call mine "assets", so:
STATICFILES_DIRS = (
os.path.join(os.path.dirname(__file__), 'assets'),
)
It was a silly error. I forgot to add fbtest to INSTALLED_APPS, so the static file machinery didn't manage static files for this app.
This problem is realy evergreen...
Some hints:
TEMPLATE_CONTEXT_PROCESSORS = (
# ...
'django.core.context_processors.static',
# ...
)
INSTALLED_APPS = (
# ...
'django.contrib.staticfiles',
# ...
)
Did you use? django-admin-collectstatic command?
Can you help add show_indexes=True in url settings?
Some symbolic link?
Run app with --adminmedia=../grappelli/static/grappelli arg.?
My settings for django 1.4 (no grappelli):
urls.py
if settings.DEBUG:
urlpatterns = patterns('',
url(r'^%s(?P<path>.*)$' % settings.STATIC_URL.lstrip('/'), 'django.views.static.serve',
{'document_root': settings.STATIC_ROOT, "show_indexes": True}),
url(r'^%s(?P<path>.*)$' % settings.MEDIA_URL.lstrip('/'), 'django.views.static.serve',
{'document_root': settings.MEDIA_ROOT, "show_indexes": True}),
) + urlpatterns
settings.py
MEDIA_ROOT = os.path.join(PROJECT_DIR, 'media')
STATIC_ROOT = os.path.join(PROJECT_DIR, 'static')
MEDIA_URL = '/media/'
STATIC_URL = '/static/'
ADMIN_MEDIA_PREFIX = '/static/admin/'
TEMPLATE_CONTEXT_PROCESSORS = (
# ...
'django.core.context_processors.static',
# ...
)
INSTALLED_APPS = (
# ...
# 'django.contrib.staticfiles',
# ...
)
I'm a little stumped. In development, I'm trying to serve both static AND dynamic files for my app in DJango 1.3. I love the new static features, but I can't seem to get this to work properly.
When I read the docs, it looks like the following should work. It serves dynamic stuff fine, but not static.
urlpatterns += staticfiles_urlpatterns()
if settings.DEBUG:
urlpatterns += patterns('',
url(r'^media/dynamic/(?P<path>.*)$', 'django.views.static.serve', {
'document_root': settings.MEDIA_ROOT,
}),
)
In django 1.3 static and dynamic content have been separated. to use the new features, set up your project like this:
project
|- app1
|- media # exists only on server/folder for dynamic content
|- static-root # exists only on server/folder for static content
|- static # folder for site-specific static content
|- settings.py
|- manage.py
`- urls.py
settings.py
from os import path
PROJECT_ROOT = path.dirname(path.abspath(__file__)) #gets directory settings is in
#-- dynamic content is saved to here --
MEDIA_ROOT = path.join(PROJECT_ROOT,'media')
MEDIA_URL = '/media/'
#-- static content is saved to here --
STATIC_ROOT = path.join(PROJECT_ROOT,'static-root') # this folder is used to collect static files in production. not used in development
STATIC_URL = "/static/"
ADMIN_MEDIA_URL = STATIC_URL + 'admin/' #admin is now served by staticfiles
STATICFILES_DIRS = (
('site', path.join(PROJECT_ROOT,'static')), #store site-specific media here.
)
#-- other settings --
INSTALLED_APPS = (
...
'django.contrib.staticfiles',
...
)
urls.py
from django.conf import settings
#your URL patterns
if settings.DEBUG:
urlpatterns += staticfiles_urlpatterns() #this servers static files and media files.
#in case media is not served correctly
urlpatterns += patterns('',
url(r'^media/(?P<path>.*)$', 'django.views.static.serve', {
'document_root': settings.MEDIA_ROOT,
}),
)
Check STATIC_URL from settings.py, what is the value ?