Just for some context, I am testing running a Django (1.4) app behind nginx+gunicorn on webfaction in order to run the admin parts securely. This is working fine. The nginx proxy is redirecting requests from http://domain.com/admin to https://domain.com/admin and Django is serving everything up without issue. The greater issue is the static files. I have these being served up from a separate static directory that is accessed both via http and https. My problem is how to render the static urls in my app's templates as well as the admin interface templates in such a way that the appropriate prefix is applied (http or https) depending on whether the request is secured or not.
For my app's templates, I've used the {{ STATIC_URL }}path/to/resource convention, which allows me to easily adjust the STATIC_URL context variable in a template_context_processor function. But this doesn't have any effect on the administrative templates which use the {% static path/to/resource %} templatetag to render the url.
The best I have come up with is to make two url options in settings.py:
STATIC_URL = 'https://mydomain.com/static/'
NON_SECURED_STATIC_URL = 'http://mydomain.com/static/'
Then added the following function to TEMPLATE_CONTEXT_PROCESSORS:
def set_static_url(request):
if not request.is_secure():
return { 'STATIC_URL': settings.NON_SECURED_STATIC_URL }
This is actually working, but it seems rather hackish. I'm also quite new to Django and I feel there must be a better or more appropriate way of doing this.
Related
So I'm trying to run multiple instances of Django on a server for now, one under /dev/, one under /test/, etc..
The web server is setting the correct SCRIPT_NAME setting and I can serve pages, templates, the whole admin panel fine, except for static assets. Static assets are served by Django using WhiteNoise.
The application is supposed to use the value of SCRIPT_NAME as the static URL, ie all static assets are served from the application root.
So far I've tried the following settings against the admin panel:
# SCRIPT_NAME = '/dev/' Set in env
# URL for static assets should be `/dev/`
STATIC_URL = '/' # Browser looks for static assets in `/`, drops script_name
STATIC_URL = None # Browser looks for static assets in `/`, drops script_name
STATIC_URL = `/dev/` # Browser looks for static assets in '/dev/dev/`
I'm wondering if I'm missing a setting here or if the problem might be elsewhere. Going by the docs I understand that STATIC_URL = '/' should work?
Finally got a working config for running my app under /dev/:
# SCRIPT_NAME = '/dev/' set from uwsgi, or use FORCE_SCRIPT_NAME
STATIC_URL = '/dev/'
WHITENOISE_STATIC_PREFIX = '/'
This seems to correctly prepend /dev/ to all static URLs, and makes whitenoise serve static assets from that directory (no subdir).
Not sure if this is the correct approach though?
Thanks #Geotob. this saved me after so many hours of research. As per docs WhiteNoise 6.2 is supposed to handle this automatically. but some how its not working
http://whitenoise.evans.io/en/stable/django.html?highlight=WHITENOISE_STATIC_PREFIX#WHITENOISE_STATIC_PREFIX
I was hit with this issue when i tried to deploy django with nuxt frontend on Digital Ocean's app platform offering. where my django-drf was running on /api. the admin page wouldn't load with static files on /api/admin/....
finally this setting is working for me. below is my snippet if anyone stumbles upon similar situation.
app_route = os.getenv("APP_PLAT_ROUTE", None)
if app_route is not None:
rel_app_route = os.path.relpath(app_route, '/')
FORCE_SCRIPT_NAME = "/{0}".format(rel_app_route)
WHITENOISE_STATIC_PREFIX = '/static/'
STATIC_URL = "/{0}/static/".format(rel_app_route)
I have a Django project set up in the following way:
Apache serving Django via WSGI on https://example.com and https://example.com.
Apache also serving http://static.example.com and https://static.example.com.
The templates are set up as such in regards to static files (for example):
{% load staticfiles %}
[...]
<script src="{% static 'site/js/main.js' %}"></script>
There is however a problem. When the Django site is accessed via HTTPS, browsers tend to complain about security as the static files are STILL served via HTTP. For instance Chrome:
So the question is, is there a way to tell Django to use https://static.example.com/ as a STATIC_URL when the site is accessed via HTTPS?
Since you're using a separate subdomain for your assets, you can use a protocol-relative URL which always serves on the same protocol as the source page:
STATIC_URL = "//static.example.com"
This is my folder structure
Music
-Music
-Feature
-static
-feature
core.css
-css
other css files
-js
-img
-templates
404.html
500.html
index.html
-feature
about.html
detail.html
template.html
manage.py
views.py
from django.shortcuts import render
def error404(request):
return render(request,'404.html')
urls.py
urlpatterns = [
url(r'^featured/(?P<pk>[0-9]+)/$', views.DetailView.as_view(), name='detail'),
url(r'^about/$', views.about, name='about'),
url(r'^FAQ/$', views.faq, name='faq'),
]
handler404 = 'mysite.views.error404'
The custom 404.html file gets rendered but with no css.And normally the css works fine on other pages but when I set debug=falseto check the custom 404 error page in settings.py the css for the entire project disappears. Something to do with folder structure or some other problem?
edit: core.css is the main css file and the part with other css files contains css for plugins
It's about serving static files. When you use DEBUG = True then django takes care about them otherwise your server should do it. Django in debug mode uses this view. The warning from there:
This view will only work if DEBUG is True.
That’s because this view is grossly inefficient and probably insecure.
This is only intended for local development, and should never be used
in production.
You can run your server with --insecure option just to test 404 error or you can explicilty create url for that page to check its styling:
Use the --insecure option to force serving of static files with the
staticfiles app even if the DEBUG setting is False. By using this you
acknowledge the fact that it’s grossly inefficient and probably
insecure. This is only intended for local development, should never be
used in production and is only available if the staticfiles app is in
your project’s INSTALLED_APPS setting. runserver --insecure doesn’t
work with CachedStaticFilesStorage.
Your handler404 and view are okay. But you don't need them. Just a custom 404 template is enough. See: https://docs.djangoproject.com/en/1.8/topics/http/views/#the-http404-exception
In order to use the Http404 exception to its fullest, you should
create a template that is displayed when a 404 error is raised. This
template should be called 404.html and located in the top level of
your template tree.
The template is in the right location. I think the problem is serving your static files. Open developer tools in your browser to see what resources fail to load (console, network or sources tab). Inspect the paths. Is there an external style sheet link in the head section of the 404 source? (elements tab or view source code).
https://docs.djangoproject.com/en/1.8/howto/static-files/
I have a problem about serving admin uploaded files in my templates.
I set:
MEDIA_URL='/media/'
MEDIA_ROOT = 'assets/'
and my models are like:
mainPhoto = models.ImageField(upload_to="articles/")
When in my templates, I try:
<img src="{{MEDIA_URL}}{{article.mainPhoto}}" />
The image doesn't show up on the website.
I found one deprecated solution with the django .serve(), but I hope to avoid using it.
I was looking everywhere and didn't find any answer, so I hope someone here will be able to help me.
There are two parts to make this work. First is the Django configuration. There are really two settings for this which you have already mentioned - MEDIA_URL and MEDIA_ROOT. As already noted in the comments the MEDIA_ROOT has to be an absolute path. For example:
MEDIA_ROOT = `/abs/path/to/project/media/`
Second part is actually serving the files. If you are in production, you NEVER want to serve your static or media files through Django so you should configure Apache or nginx or whatever server system you are using to serve the files instead of Django. If you are on the other hand still developing the app, there is a simple way to make Django serve media files. The idea is to modify your urls.py and use the Django's static files server to serve media files as well:
# urls.py
from django.conf import settings
from django.conf.urls.static import static
urlpatterns = patterns('',
# other patterns
) + static(settings.MEDIA_URL, document_root=settings.MEDIA_ROOT)
More about this approach at Django docs.
Also FYI, you probably should not use {{MEDIA_URL}}{{article.mainPhoto}} to get the url of an image. This approach will break for example if you will no longer use file system storage for static files and will switch to something different like Amazon S3. It is always a good idea for the storage backend to figure out the url:
<img src="{{article.mainPhoto.url}}" />
I've looked through countless answers and questions trying to find a single definitive guide or way to do this, but it seems that everyone has a different way. Can someone please just explain to me how to serve static files in templates?
Assuming I've just created a brand new project with Django 1.4, what all do I need to do to be able to render images? Where should I put the media and static folders?
Put your static files into <app>/static or add an absolute path to STATICFILES_DIRS
Configure your web server (you should not serve static files with Django) to serve files in STATIC_ROOT
Point STATIC_URL to the base URL the web server serves
Run ./manage.py collectstatic
Be sure to use RequestContext in your render calls and {{ STATIC_URL }} to prefix paths
Coffee and pat yourself on the back
A little bit more about running a web server in front of Django. Django is practically an application server. It has not been designed to be any good in serving static files. That is why it actively refuses to do that when DEBUG=False. Also, the Django development server should not be used for production. This means that there should be something in front of Django at all times. It may be a WSGI server such as gunicorn or a 'real' web server such as nginx or Apache.
If you are running a reverse proxy (such as nginx or Apache) you can bind /static to a path in the filesystem and the rest of the traffic to pass through to Django. That means your STATIC_URL can be a relative path. Otherwise you will need to use an absolute URL.
The created project should have a static folder. Put all resources (images, ...) in there.
Then, in your HTML template, you can reference STATIC_ROOT and add the resource path (relative to the static folder)
Here is the official documentation:
How to manage static files: https://docs.djangoproject.com/en/1.4/howto/static-files/
Static Files in general: https://docs.djangoproject.com/en/1.4/ref/contrib/staticfiles/
If you are planning to to deploy in a production type setting then you should read the section here: https://docs.djangoproject.com/en/1.4/howto/static-files/#staticfiles-production
Generally you put our static and media folders outside of the django project app
Define your STATICFILES_DIRS, STATIC, and MEDIA path in the settings.
Create staticfiles folder beside your templates folder, urls.py, settings.py, etc...
You don't have to create media folder because it will automatically created when you upload images.
In your urlconf put this one:
from django.conf.urls import patterns, include, url
from django.contrib import admin
from django.conf import settings
from django.contrib.staticfiles.urls import staticfiles_urlpatterns
from django.conf.urls.static import static
admin.autodiscover()
urlpatterns = patterns('',
.............
) + static(settings.MEDIA_URL, document_root=settings.MEDIA_ROOT)
urlpatterns += staticfiles_urlpatterns()
In templates:
{% load static %}
<img src="{% static 'images.png' %}">
<img src="{{MEDIA_URL}}images.png">