Consider the following setup:
urls.py
if not settings.PRODUCTION:
urlpatterns += patterns('',
(r'^admin-media/(?P<path>.*)$', 'django.views.static.serve',{'document_root': settings.LOCAL_ADMIN_MEDIA_ROOT, 'show_indexes': True}),
(r'^media/(?P<path>.*)$', 'django.views.static.serve',{'document_root': settings.LOCAL_MEDIA_ROOT, 'show_indexes': True}),
)
settings.py
if not PRODUCTION:
ADMIN_MEDIA_PREFIX = '/admin-media/'
So when running on the local development server the media files should be served through the runserver, right? The media route is found, however "Permission denied" is returned for every request (but only one admin media, the regular media works fine).
So I did some checking into it. It turns out, if the ADMIN_MEDIA_PREFIX is set to the same value as the route...
(r'^admin-media/(?P<path>.*)$', 'django.views.static.serve', ... ),
ADMIN_MEDIA_PREFIX = '/admin-media/'
...then the runserver will always return "Permission denied."
However, if ADMIN_MEDIA_PREFIX is different than the route name...
(r'^admin-media/(?P<path>.*)$', 'django.views.static.serve', ... ),
ADMIN_MEDIA_PREFIX = '/non-sense-prefix/'
... then the files will be served (though I have to manually browse to be able to see them as all the media links are broken with http://localhost:8000/non-sense-prefix/whatever.jpg).
What's the deal here?
In the mean time I've solved the problem by a little hack to change directories...
(r'^admin-media/(?P<path>.*)$', 'django.views.static.serve', ... ),
ADMIN_MEDIA_PREFIX = '/admin-media/../admin-media/'
...but I would really rather configure this properly. It seems django is trying to be smart and do something on my behalf, but messing things up in the process. Any ideas?
EDIT --
I'm manually serving the admin media because I'm using grappelli which provides replacement for the admin templates/media.
If you're running Grappelli, you can set the admin media when using runserver by specifying the command line argument --adminmedia. Here is an example:
python manage.py runserver --adminmedia=/path/to/grappelli/media
Where /path/to/grappelli/media is the complete path to your Grappelli installation's media directory.
You don't need to specifically serve the admin media while using the development server - this should happen automatically.
I think it is simpler to just symlink in your local system to the django admin media, the same directory that you use in production, than to subject to a lot of if PRODUCTION within settings.
As Daniel rightly pointed out, django serves admin media by default. Anymore configuration is not required. So the problem is perhaps something different. Try chmod 777 on the templates directory, It may fix the problems.
Related
Using Django, I've deployed my web app to http://159.223.177.51/. To login to see the images, use sof///stackoverflow123
I can see the custom fonts and CSS so I know static is working. However, none of the media files are showing. When I try to upload a photo using the forms on the web app, it gives me a 505 error.
On localhost on my desktop computer, all the images work properly using manage.py runserver. When I uploaded it to ubuntu and edited the new location of the files, none of it works. I've looked through similar posts like this but it didn't solve it.
Here's what I tried in settings.py:
MEDIA_ROOT= os.path.join(BASE_DIR,'/home/stelity/myonlinefp/foodpantry/media')
MEDIA_URL= "/media/"
DEBUG = FALSE
And in urls.py:
]+ static(settings.MEDIA_URL, document_root=settings.MEDIA_ROOT)
I also edited the permissions of the media folder to allow everyone to read/write/execute and that didn't solve it either.
I'm trying to get my Django app to play audio files (supposedly) uploaded by users via a form. Said files are tied to a model :
# models.py
class Doc(models.Model):
# ...
tape = models.FileField()
The uploading and saving parts are working fine, and the files are stored where they should be :
- djangoproject
|
- docapp
|
- media <- here
So, in order to get where I want, I added these two lines to the settings.py file MEDIA_ROOT = os.path.join(BASE_DIR, 'docapp/media/') and MEDIA_URL = 'docapp/media/'.
I hoped to be able to link to the audio files thus:
# templates/docapp/index.html
...
<audio src='{{ doc.tape.url }}' controls></audio>
Unfortunately, this wasn't working because the link generated by doc.tap.url (http://localhost/docapp/media/filename.aac) was returning a 404 error.
After a lot of googling I found this answer, which I happily copy-pasted into my app ... and it worked. This is the code in question :
# urls.py
from django.conf import settings
from django.conf.urls.static import static
urlpatterns += static(settings.MEDIA_URL, document_root=settings.MEDIA_ROOT)
The problem is that I'm not comfortable with inserting code in my apps that I don't understand. I did some research about the static() function and all I could get is this :
Helper function to return a URL pattern for serving files in debug mode
Does this mean that the static function should not be used in production? If so, what should I be using in production? And what exactly does it do?
EDIT To be clear, the generated URL after injecting the solution is the same as the one generated without it. Yet, it only works when the static() function is present.
EDIT 2 I forgot to mention that the 404 errors persisted even after I chmoded the media folder to allow others to read-access it.
Thanks in advance!
You shouldn't do anything. No errors no problem. The docs write about development server and serving static files AND that it is for development only. In a production environment you configure your server (Apache, NGNIX or third party like S3) to serve the files. That's all.
Try to configure media files and access the file via it's url. If it works, try the {{ doc.tape.url }} template tag.
In your development environment your media may live in /media/ (route and directory). While on production it may be something like media.example.com. Running Django with the settings for that environment will change all static/media domains and paths to their correct locations.
You may split settings file into a settings file for each environment (production, acceptance, development). Like this:
project/
settings/
__init__.py
base.py
local.py
staging.py
test.py
production.py
You can run your project with a specific env: ./manage.py runserver --settings=project.settings.development. Do not repeat yourself and put development specific settings in development.py and from base import * so that base.py contains the default settings.
This project and settings layout is taken from the book Two Scoops of Django. It is just an example. Adjust to your own needs.
Yes, django.conf.urls.static.static is only for development and not for production. For production, you should just need to configure your MEDIA_URL and MEDIA_ROOT settings and have your webserver serve the MEDIA_ROOT directory in the MEDIA_URL path.
Basically adding that in the URL urlpatterns += static(settings.MEDIA_URL, document_root=settings.MEDIA_ROOT) will make the media files in the URL existing. Try removing that and visit your media file in the URL and you will receive a 404 not found. It's very similar to the concept that you are inserting a view for rendering the media files
Currently, I have been having issues with getting my static and media to work with django on heroku. My static is finally working, but my media won't, and this is my first in any sort of production environment, so I'm not sure if it is done correctly. My media files will work after an upload, however they no longer work once I edit something unrelated and try to push it to heroku typing:
git add .
git commit -m "changes"
git push heroku master
So after I update my heroku app, a user would have to re-add their media files in order for them to work every time I do an update. As far as the code I have so far:
#settings.py
DEBUG = False
MEDIA_ROOT = 'media'
MEDIA_URL = '/media/'
STATIC_ROOT = 'static'
STATIC_URL = '/static/'
STATICFILES_DIRS = (
'static',
)
#urls.py
urlpatterns += staticfiles_urlpatterns()
if not settings.DEBUG:
urlpatterns += patterns('',
(r'^static/(?P<path>.*)$', 'django.views.static.serve', {'document_root': settings.STATIC_ROOT}),
(r'^media/(?P<path>.*)$', 'django.views.static.serve', {'document_root': settings.MEDIA_ROOT}),
)
I'm pretty lost on what to do, and I have tried several different changes to my urls and settings without any luck. I have read other posts and tried them, I've read the docs, and I still don't really understand unfortunately. Everything was working fine in development, but I had different code for my project in development under my settings. Any help would be greatly appreciated.
EDIT
So after more digging, I decided to give Amazon S3 a try for handling my media files. I'm still not really sure how uploading files to S3 works, but I already created a S3 bucket and set my heroku settings (AWS_ACCESS_KEY_ID, AWS_SECRET_ACCESS_KEY, S3_BUCKET_NAME). I am still unsure of what my media and static settings should look like. If anyone can point me in the right direction, I would really appreciate it.
Ok so I finally got things working the way they should after a lot of banging my head against the wall. I am now using Amazon S3 for my static and media files (partially thanks to this post, and the most helpful post for me in getting things set up correctly was here. If you are using heroku, you probably want to look into using S3 for static and media files. Yes, it is something else you have to try to configure and integrate, and no it is not free, but if you just push back you may find yourself using it in the end anyway, so save yourself some time. This was also helpful for separating static and media into separate dierctories.
I'm facing quite a strange issue with Django, my STATIC_URL is /static/ and I've got an app installed using pip as -e git+git://github.com/foo/bar.git#egg=bar which loads it into the virtualenv src folder.
Now, I'm trying to GET a static file related to this app as /static/bar/js/something.js and the src folder does have a bar/bar/static/bar/js/something.js file. Even if I findstatic bar/js/something.js it gives me a valid path to the file. However when I access it using the browser, I'm 301'd to /static/bar/js/something.js/ which 404s.
Why would this be happening?
Even poking around with staticfiles app, I was able to see that it recognizes my app as installed and that its static folder exists. However somehow the static files aren't being served.
Make sure that you have set up the django development server to actually server the static files for you.
urls.py
from django.contrib.staticfiles.urls import staticfiles_urlpatterns
# ... the rest of your URLconf goes here ...
urlpatterns += staticfiles_urlpatterns()
Try using this urlpattern:
url( r'(?P<path>.*)$', 'django.views.static.serve', {'document_root': '/path/to/file/'}),
Does anyone have a simple step-by-step tutorial about serving static files on a Django production app? I read the Django docs and it sounds really complicated... I'm trying to go the route of serving static files using a different server like lighttpd, nginx, or cherokee, but setting these up is all Greek to me. I downloaded lighttpd, tried to follow the instructions to install, and within a few seconds got an error. Missing this or that or whatnot... I'm not a UNIX whiz and I'm not very good at C/C++, so all this ./configure and MAKE install are gibberish to me... So I guess my immediate questions are:
Which server would you recommend to serve static files that's easy to install and easy to maintain?
Assuming I actually get the server up and running, then what? How do I tell Django to look for the files on that other server?
Again, anyone has step-by-step tutorials?
Thanks a lot!
Sorry, don't have a step by step tutorial. But here is a high level overview that might help:
You probably want to go with the Apache server ( http://httpd.apache.org/) This comes with most *nix distributions.
You then want to use mod python (or as the commenter pointed out mod_wsgi: http://docs.djangoproject.com/en/dev/howto/deployment/modwsgi/) to connect to Django : http://docs.djangoproject.com/en/dev/howto/deployment/modpython/?from=olddocs. Once you complete this step, Apache is now fronting for Django.
Next you want to collect the static files in your Django into one directory and point apache at that directory. You can do this using the the ./manage.py collectstatic if you used django.contrib.staticfiles (http://docs.djangoproject.com/en/dev/howto/static-files/.)
So the trick is you're not telling Django to delegate serving static files to a specific server. Rather you're telling httpd which urls are served via Django and what urls are static files.
Another way of saying this is that all requests come to the Apache web server. The webserver, according to the rules you specify in httpd.conf, will decide whether the request is for a static file or whether it is for a dynamic file generated by django. If it for a static file it will simply serve the file. If the request is for a dynamic file it will, via modpython, pass the request to Django.
Hope that helps.
Development
STATICFILES_DIRS should have all static directories inside which all static files are resident.
STATIC_URL should be /static/ if your files are in local machine otherwise put the base URL here e.g. http://example.com/.
INSTALLED_APPS should include django.contrib.staticfiles.
In the template, load the staticfiles module:
{% load staticfiles %}
<img src='{% static "images/test.png" %}' alt='img' />
Production
Add STATIC_ROOT that is used by Django to collect all static files from STATICFILES_DIRS to it.
Collect static files:
$ python manage.py collectstatic
Add the path to urls.py:
from . import settings
urlpatterns = patterns('',
..
url(r'^static/(?P<path>.*)$', 'django.views.static.serve', {'document_root':settings.STATIC_ROOT)}),)
More detailed articles are listed below:
http://blog.xjtian.com/post/52685286308/serving-static-files-in-django-more-complicated
http://agiliq.com/blog/2013/03/serving-static-files-in-django/
With the latest Django version like Django 3.2.6 I was having issues serving media and static files both in the dev and prod environment while DEBUG = False.
So I got around a solution that came from multiple stack overflow posts.
Import appropriate functions to urls.py
from django.urls import include, path, re_path
from django.views.static import serve
Define static URL pattern list to urls.py
static_urlpatterns = [
re_path(r"^media/(?P<path>.*)$", serve, {"document_root": settings.MEDIA_ROOT}),
re_path(r"^static/(?P<path>.*)$", serve, {"document_root": settings.STATIC_ROOT}),
]
Assuming your STATIC_ROOT and MEDIA_ROOT is already defined in settings.py file
Just include static_urlpatterns in urlpatterns
urlpatterns = [
path("admin/", admin.site.urls),
path("api/", include(api_urlpatterns)),
path("", include(static_urlpatterns)),
]
Hope it works for you both in the dev and prod environment when DEBUG = FALSE. Thank you.
Updated for urls.py
the url(....) format doesn't work anymore in urls.py for Django 3.0.7.
you need to do then:
urls.py:
from django.conf import settings # to import static in deployment
from django.conf.urls.static import static # to import static in deployment
....
urlpatterns = [
....
] + static(settings.STATIC_URL, document_root=settings.STATIC_ROOT) # to import static in deployment
Reference: https://docs.djangoproject.com/en/3.0/howto/static-files/