Django: Problem with template paths? - django

So after a few hours of irritation i finally got my django site up and running! The only problem i have now is that all the stylesheets/images are linked incorrectly. Or, well, they are linked correctly but django wont give me the files, kind of.
This is how it's set up:
views.py:
from django.shortcuts import render_to_response
def home(request):
return render_to_response('index.html')
urls.py:
from django.conf.urls.defaults import patterns, include, url
urlpatterns = patterns('',
# Examples:
url(r'^$', 'mysite.views.home', name='home'),
)
and that brings up index.html, but none of the other files are shown, like images, stylesheets etc. How do I solve this? I have a feeling it's really easy!? I tried googling, but couldn't find anything.
Thanks in advance,
qwerty

It sounds like what you're looking for is the ability to serve static files.
Basically, you'll need to add a folder somewhere in your project to save the media to. Then, you'll need to edit your urls.py and settings.py files to accommodate access to your new static media directory.
urls.py
urlpatterns = patterns('',
# Examples:
url(r'^$', 'mysite.views.home', name='home'),
(r'^static/(?P<path>.*)$', 'django.views.static.serve', {'document_root':
settings.STATIC_ROOT}),
)
settings.py
PROJECT_ROOT = os.path.abspath(os.path.dirname(__file__))
# Should be the location where you put your static folder.
# Should be different for testing and production environments.
STATIC_ROOT = os.path.join(PROJECT_ROOT, 'media')
# This is assuming that your settings.py file is in path/to/project/ and your
# static files are in path/to/project/media/
Then in your template you can do this:
< img src="/static/my_image.jpg" / >
Or whatever you want. This will work for javascript, css and image files.

Expanding on Shamanu4's comment: what you're asking for is how static files are served. For development purposes, you can use the static file server.
Long term, though, this is not an optimal solution. The easy way is to segregate all your static files and serve them directly through your web browser via a different path. In Apache, this static file path can be inside your Django path if you configure the static path first.
If you need high performance, though, the Django team recommends that you use a lightweight, speed-optimized server (such as lighttpd) to serve static files and another server with WSGI support (such as Apache) to serve Django.
In the Django project I have at work, I have Django served from /djangoprojname/ and static files served from /djangoprojname/static/. On disk, the static directory is at the same level as my Django project's directory. both of which are in a Mercurial repository. Within static/, I have css/, js/, and img/, and within those directories, I have one directory per app, named the same as the app. This keeps things from getting messy.
My django.conf (in /etc/httpd/conf.d on Fedora or RHEL) looks something like:
WSGIDaemonProcess djangoprojname threads=15
WSGISocketPrefix /var/run/wsgi/wsgi
Alias /djangoprojname/static/ /var/www/djangoprojname/static/
Alias /djangoprojname/admin/media/ /usr/lib/python2.6/site-packages/django/contrib/admin/media/
WSGIScriptAlias /djangoprojname /var/www/djangoprojname/django.wsgi
WSGIProcessGroup djangoprojname
<Directory /var/www/djangoprojname>
Order deny,allow
Allow from all
</Directory>
<Directory /usr/lib/python2.6/site-packages/django/contrib/admin/media>
Order deny,allow
Allow from all
</Directory>
For development, I added this to the end of my project's urls.py:
# Only serve static media if in development (runserver) mode.
if settings.IS_DEV:
urlpatterns += patterns('',
url(r'^static/(?P<path>.*)$', 'django.views.static.serve',
{'document_root': settings.MEDIA_ROOT,
'show_indexes': True}),
)
settings.IS_DEV is set in my settings.py to True if this is running on a development server. manage.py is modified to set an environment variable if runserver is used, and settings.py checks for this variable. MEDIA_ROOT is set to the path to the static directory.

You are probably having problem with MEDIA_ROOT and MEDIA_URL in your settings.py. Please refer to http://docs.djangoproject.com/en/1.3/ref/settings/#media-root

Related

Why doesn't Django serve static files when the dubug=False in settings?

when I tried to run the project, static files are missing, and the settings.debug is set to False.
Django does not serve static files in production (when DEBUG = False) because doing so would be in their own words (As stated in the section Serving static files during development of the documentation):
This method is grossly inefficient and probably insecure, so
it is unsuitable for production.
Why is this inefficient one might say? Well static files are mostly larger in size than your normal HTML files, plus a website is bound to have lots of static files. If Django served static content even in production much of the time of the server would be wasted in serving these static files. Plus to serve multiple requests at the same time we run multiple Django processes simultaneously, if there are many requests for static files this will cause the processes to waste time serving them, causing other requests to wait if there are no free processes.
Plus as #Reda Bourial mentions in their comment Django doesn't handle compression well (One would want to compress their static files so that less bandwidth is required, both by the server and the client). Furthermore Django should focus more on the task it is designed for, which is rendering the pages requested by users (A CPU bound task), whereas serving static files is mostly just an Input / Output (I/O) task and for Django to spend time on these tasks (even when it is not efficient at them) is clearly a waste.
Servers like NGINX or Apache can serve static files much more efficiently, hence it is best to use them in production instead of having Django do it. For details on how to configure static files for production see Deploying static files [Django docs]
Actually in Django, while you run your project on the development server it won't serve your static files when you try to serve the static files after changing DEBUG settings to False. It will work properly on the production or stagging server but not on localhost server.
Still, there is a way to do this you can get by running your development server on insecure mode.
Try this,
python manage.py runserver --insecure
it is not recommended, but if you are just getting started and want to understand more about what's going on, then you can also link directly:
urls.py:
from django.conf.urls.static import static
from django.contrib import admin
from djangoapp import settings
from webtools.views import *
from django.urls import path, include
"""
direct link on the server in production
"""
from django.views.static import serve as mediaserve
from django.conf.urls import url
urlpatterns = [
path('admin/', admin.site.urls),
path('', include('webtools.urls')),
]
if settings.DEBUG:
import debug_toolbar
urlpatterns = [
path('__debug__/', include(debug_toolbar.urls)),
] + urlpatterns
urlpatterns += static(settings.MEDIA_URL, document_root=settings.MEDIA_ROOT)
else:
# direct link on server in production
urlpatterns += [
url(f'^{settings.MEDIA_URL.lstrip("/")}(?P<path>.*)$', mediaserve, {'document_root': settings.MEDIA_ROOT}),
url(f'^{settings.STATIC_URL.lstrip("/")}(?P<path>.*)$', mediaserve, {'document_root': settings.STATIC_ROOT}),
]
settings.py:
DEBUG = False
.
.
.
STATIC_URL = '/static/'
STATIC_ROOT = os.path.join(BASE_DIR, 'static')
STATICFILES_DIRS = []
MEDIA_ROOT = os.path.join(BASE_DIR, 'media')
MEDIA_URL = '/media/'

Loading images in a static file

So I have completed the Django tutorial, play around with it some, and feel that I have a good understanding of Django. The only problem I am facing is that when I try to display a static page for a landing page, I cannot seem to get any images to load.
First off I have tried two different methods of displaying a static landing page.
First:
# main app urls.py
from django.conf.urls import patterns, include, url
from django.contrib import admin
admin.autodiscover()
urlpatterns = patterns('',
url(r'^$', TemplateView.as_view(template_name="landing/index.html")),
url(r'^polls/', include('polls.urls', namespace="polls")),
url(r'^admin/', include(admin.site.urls)),
)
This is the main app's urls.py and I use the TemplateView to display the static index.html which is located at 'my_app/templates/landing/index.html'.
This is all and well until I try to add a static image into the index.html file. No matter where I put the image file I cannot seem to get it to display. In the index.html template I have tried different methods of using static as well as trying different direct paths without the need for the embedded python code. How am I supposed to display images and where should they be located?
The second method I found that worked for just displaying the static page (not the image) was to create a new app called landing and have that simply display a static page from the urls.py in the same manner(using TemplateView). Is this method better? I still had the same problems in displaying an image within the static page as the first method, which makes me think it has something to do with the TemplateView.
Am I doing this completely wrong? What are my options? I am using Django 1.5.1.
Thanks in advance!
It is a bit awkward to serve statics files with Django. This is because they have the conception that static files such as images must be in another domain or server for performance/security reasons.
To serve static content with django do this:
# urls.py
# add this lines at the end
from django.conf.urls.static import static
from django.conf import settings
from django.contrib.staticfiles.urls import staticfiles_urlpatterns
urlpatterns += staticfiles_urlpatterns()
urlpatterns += static(settings.MEDIA_URL, document_root=settings.MEDIA_ROOT)
Then in settings.py define the directory where the images/css/js and similar static contents are:
# settings.py
import os
settings_dir = os.path.dirname(__file__)
PROJECT_ROOT = os.path.abspath(os.path.dirname(settings_dir))
STATIC_URL = '/static/'
STATICFILES_DIRS = (
# this assumes your static contents is in <your_project>/static/
os.path.join(PROJECT_ROOT, 'static/'),
)
MEDIA_ROOT = os.path.join(PROJECT_ROOT, 'media/')
MEDIA_URL = '/media/'
Note: You may also consider images as media and place them in your media/ folder.
That should get static files served with your app. Just reference them like this href="/static/xxxx.jpg" or href="/media/xxxx.jpg".
Hope it helps!
This blog explains serving static file and might help:
http://agiliq.com/blog/2013/03/serving-static-files-in-django/

django and static css plus js files

i did a small app on django and it is using templates. Each tempalate use static files such as css, js and images. all those files in same directory as template.
template
main.html
support.html
about.html
...
css
reset.css
style.css
...
img
js
jquery.js
main.js
...
if there is was to configure django development server to load those files without editing html templates files?
i am receiving
http://127.0.0.1:8000/face/css/960_24_col.css 404 NOT FOUND 127.0.0.1:8000
this changes in settings.py didnt help me
STATIC_ROOT = 'C:/Projects/site/website/face/static/'
STATIC_URL = '/static/'
STATICFILES_DIRS = ('C:/Projects/site/website/face/static',)
You might want to use the contrib app staticfiles. At the bottom of the doc page you'll see how to use it on development server.
STATIC_URL has been defined as '/static/' so all static files will be served from /static.
In other words /face/css/960_24_col.css is incorrect.
This should be /static/face/css/960_24_col.css , assuming the face directory is located at C:/Projects/site/website/face/static/face.
Might I also advise you not to use absolute paths in your settings file. To find out the absolute path of the root of your project use something like:
PROJECT_DIR = os.path.abspath(os.path.dirname(__file__))
Here is how I serve static files via the Django dev server.
Defined in urls.py:
from os import getcwd, path as ospath
...
urlpatterns += patterns('',
(r'css/([a-zA-Z0-9_.]+.css)$', 'django.views.static.serve', {'document_root': ospath.join(getcwd(), 'css')}),
(r'images/(.*)$', 'django.views.static.serve', {'document_root': ospath.join(getcwd(), 'images')}),
(r'js/([a-zA-Z0-9_.]+.js)$', 'django.views.static.serve', {'document_root': ospath.join(getcwd(), 'js')})
)

Django on Heroku - Broken Admin Static Files

I have a Django app running on Heroku/Cedar, configured as per the instructions at https://devcenter.heroku.com/articles/django
Using gunicorn as per Heroku's instructions fails to include the static files required for Django's admin to function. I can change the Procfile to "manage.py run_gunicorn" for local development, but that doesn't fly on Heroku.
I've searched all over for a fix - is there some way to include the admin static files without throwing them on S3 with my other static files?
If you use runserver and configure your app with DEBUG=True, then it will serve the admin files just like on your development machine. However, this is definitely not the recommended way to do it, and I would suggest that you put them on S3.
Using the django-storages app it's very easy to configure collectstatic to automatically push all the admin files to S3. You can find directions here
Check out this post: http://matthewphiong.com/managing-django-static-files-on-heroku
If that doesn't work for you try adding the following to your urls.py after the normal url pattern tuple. Make sure you have your STATIC_ROOT set and you've run collect static on your local environment all before pushing to heroku.
urlpatterns += patterns('',
url(r'^static/(?P<path>.*)$', 'django.views.static.serve', {
'document_root': settings.STATIC_ROOT,
}),
)
just add these instead
from django.contrib.staticfiles.urls import staticfiles_urlpatterns
urlpatterns += staticfiles_urlpatterns()
using django 1.4.1
It seems little late compared to the asked date. But I got into this issue and spent 30 mins on what I did wrong. So here it is the magic solution for those who might fall in this trap.
There is some problem with Heroku's django.contrib.staticfiles.urls
SOLUTION
You need to install dj-static (Link to download) on your Heroku setup.
It's a Django middleware utility that allows to properly serve static assets from production with a WSGI server like Gunicorn.
I hope this will help someone.
create 'static' folder into your 'project_directory'.
set the 'STATIC_ROOT' path in 'settings.py' file which can serve your admin-site's static files.
STATIC_ROOT = (os.path.join(os.path.dirname(__file__), '..', 'static'))
Add STATIC_ROOT in '/urls.py'
from django.conf import settings
urlpatterns += patterns('',
url(r'^static/(?P<path>.*)$', 'django.views.static.serve', {
'document_root': settings.STATIC_ROOT,
}),
)
Run the following command that will copy all the admin static files into project's static folder.
python manage.py collectstatic
Now do git add, commit and push heroku master.
If you are deploying to Heroku without using whitenoise (which I would suggest), definitely use dj_static https://pypi.python.org/pypi/dj-static!
I spent the past 3 hours trying to serve my files to heroku and dj_static worked within a matter of 2 minutes.
I got django admin working with following edits
urls.py(at the end)
import settings
urlpatterns += patterns('',
url(r'^static/(?P<path>.*)$', 'django.views.static.serve', {
'document_root': settings.STATIC_ROOT,
}),
)
Procfile
web: gunicorn hellodjango.wsgi -b 0.0.0.0:$PORT
'django.contrib.staticfiles.views.serve'
instead of
'django.views.static.serve'
Follow this to fix all static related issues with Django and heroku.
In your settings.py paste this at the end
import os
BASE_DIR = os.path.dirname(os.path.abspath(__file__))
STATICFILES_DIRS = (
os.path.join(BASE_DIR,'static'),
)
TEMPLATE_DIRS = (
os.path.join(BASE_DIR,'templates'),
)
STATIC_URL = '/static/'
Your template for a particular app should be in app_name/templates/app_name/
When you render template this is how you will specify template name
in views.py
.....
return render(request,'app_name/template_name.html',context)
For static files place your files here:
project_folder/app_name/static/app_name/css
project_folder/app_name/static/app_name/js
project_folder/app_name/static/app_name/img
to access your static file use path app_name/css/style_name.css
If you follow this, all your static files will load up fine in heroku as well as in your local development machine.

How does Django serve media files?

I have set up a Django application that uses images. I think I have set up the media settings MEDIA_ROOT and MEDIA_URL correctly. However the images don't show up. Do you know what can be the problem?
Let consider this example:
The image files are under /home/www/media/app/photos and we are trying to request http://example.com/photos/123.jpg
Should I use these settings?
MEDIA\_ROOT = /home/www/media
MEDIA_URL = http://example.com/app
UPDATE: Forgot to mention that I'm using built-in development server.
FOR DEVELOPMENT ONLY
You can setup a static media server for use with their development server by doing this in your urls.py file. I have attached the code showing how I use it (along with the forced DEBUG conditionals.)
from django.conf import settings
from django.conf.urls.defaults import *
# Uncomment the next two lines to enable the admin:
from django.contrib import admin
admin.autodiscover()
urlpatterns = patterns('',
(r'^$', 'views.index'),
# Accounts
(r'^accounts/login/$', 'views.user_login'),
(r'^accounts/logout/$', 'views.user_logout'),
# Contrib Modules
(r'^admin/(.*)', admin.site.root),
)
if settings.DEBUG :
urlpatterns += patterns('',
(r'^media/(?P<path>.*)$', 'django.views.static.serve', {'document_root': settings.MEDIA_ROOT, 'show_indexes': True}),
)
I place my MEDIA_ROOT in a subdirectory of html/media and link to it as such in settings.py
MEDIA_ROOT = os.path.join(os.path.dirname(__file__), 'html/media/').replace('\\','/')
After development is finished, the project gets deployed to the web server where static media files are then served by Apache using directives.
Serving static content from Django is discouraged from the developer themselves (if I'm not wrong, it only works when in debug mode). You should use a dedicated web server, instead.
If you really need to do that, anyway, read the documentation on how to serve static files.
This is the correct way of showing image files with ImageField. Imagine we have a user profile picture:
models.py:
UserProfile:
profilePic= models.ImageField( upload_to='PATH_TO_UPLOAD', blank=True, null=True)
settings.py:
MEDIA_ROOT = 'FULL_PATH_OF_MEDIA'
MEDIA_URL = 'URL_OF_MEDIA'
urls.py:
urlpatterns = [
.
.
.
]+ static(settings.MEDIA_URL, document_root=settings.MEDIA_ROOT)
PATH_TO_UPLOAD is the path which user upload data goes. This is sub-directory of FULL_PATH_OF_MEDIA, which means the uploaded file will have
FULL_PATH_OF_MEDIA/PATH_TO_UPLOAD
full path.Now this content can be accessed at this url:
SITE_NAME/URL_OF_MEDIA/PATH_TO_UPLOAD
I also recommend reading this on static_files vs media_files
doc
You can just add those lines to your urls.py
from django.urls import re_path
from django.views.static import serve
urlpatterns = [
...
re_path(r'^media/(?P<path>.*)$', serve,{'document_root': settings.MEDIA_ROOT}),
]
I suspect you are getting the Django 404 page. Try directly accessing one of your images and see if that's happening.
If so, your need to configure your web server to not send requests within your media hierarchy to Django but to instead serve them directly. Here is a snip from my Apache conf file. The first section tells Apache to send everything to Django. The second section has "SetHandler None" which says "handle stuff under /media in the normal way."
See http://docs.djangoproject.com/en/dev/howto/deployment/modpython/ for all the exciting details.
Partial httpd.conf file for PrinceOfPinot.com (AKA pop):
<Location "/">
SetHandler python-program
PythonAutoReload Off
PythonDebug Off
PythonPath "['/var/www/production/pop', '/usr/local/lib/python2.5/site-packages/django'] + sys.path"
SetEnv DJANGO_SETTINGS_MODULE settings
PythonHandler django.core.handlers.modpython
</Location>
<Location "/media">
SetHandler None
AddOutputFilterByType DEFLATE text/html text/css application/x-javascript
</Location>
I'm aware that the original question is with the dev server, but for anyone else who is looking for a production environment answer:
https://docs.djangoproject.com/en/1.8/howto/static-files/deployment/ provides a guide on how to have django serve files in a production environment. From the tone of the guide, it does seem to imply that it is best to have a separate web server to handle the files or use mod_wsgi with Apache