Django media not loading. staticfiles works - django

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.

Related

Using Django static() to generate audio files' URLs in production

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

Django on Azure not loading static files

I followed the tutorial below to create a django project on azure:
http://www.windowsazure.com/en-us/develop/python/tutorials/web-sites-with-django/
Everything worked fine until I tried to install the django_admin_bootstrapped app. Now all static requests return 404 error. I don't if the new app caused the problem or just exposed it.
I have this:
STATIC_ROOT = ''
# URL prefix for static files.
# Example: "http://media.lawrence.com/static/"
STATIC_URL = '/static/'
# Additional locations of static files
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(PROJECT_DIR, 'site-packages/django_admin_bootstrapped/static'),
)
I read quite a bit online and some people say you have to configure your server to serve static files. I don't have direct access to the server, it's an azure website and I deploy through git. And like I said, the admin and everything used to work before I tried to install these apps that bootstrap the admin. Now even when the app is not under INSTALLED_APPS I don't get any css or js files.
Thanks!
I had this problem and none of the suggested answers seemed to fit. My bizarre solution was to switch off Python on the Azure web site configure page.
I arrived at this odd conclusion by installing the PTVS Django sample and following the steps in this tutorial http://azure.microsoft.com/en-us/documentation/articles/web-sites-python-ptvs-django-sql/. The only difference I could fine between my site and the working tutorial was that Django was off! If someone has an explanation I would love to hear it (PHP is enabled!!!).
I found my solution on this page: http://mrtn.me/blog/2012/06/27/running-django-under-windows-with-iis-using-fcgi/
I had to create a central static folder and add a web.config for iis to serve the files. web.config below:
<?xml version="1.0" encoding="UTF-8"?>
<configuration>
<system.webServer>
<!-- this configuration overrides the FastCGI handler to let IIS serve the static files -->
<handlers>
<clear/>
<add name="StaticFile" path="*" verb="*" modules="StaticFileModule" resourceType="File" requireAccess="Read" />
</handlers>
</system.webServer>
</configuration>
Hope this helps someone!
I don't have enough rep to vote up but the answer does in fact work on Azure for me as well, and appears to be, so far, the only method of doing it. Just remember that the web.config needs to be in the right place...lol...I apparently had multiple static folders as I was trying different ways of solving this.
If after trying all the other proposed solutions you still find yourself at trouble, you may have to understand that depending on the server that's running you application is the way static files are server. Django has it's own server, which is run by using the command:
python manage.py runserver
But PAAS providers do not use this server in most of the cases. gunicorn is in most times the chosen one. Azure sometimes uses IIS's FastCGI handler but at current date it is intelligent enough to detect a django application and try to use django's default server.
So, the first step you have to take is to find out what server is azure using to run your app, and you may know that by reading azure's log:
https:// YOUR APP NAME.scm.azurewebsites.net/api/logstream
If you confirm that azure is using django's default server, you must bear in mind that django does not server static files automatically when in a production environment. You must configure the static folder's url. So in your config/urls.py set the static url, like this:
from django.conf import settings
from django.conf.urls.i18n import i18n_patterns
from django.conf.urls.static import static
from django.contrib import admin
from django.urls import include, path
urlpatterns = i18n_patterns(path('admin/', admin.site.urls), prefix_default_language=False) + \
static(settings.MEDIA_URL, document_root=settings.MEDIA_ROOT) + \
static(settings.STATIC_URL, document_root=settings.STATIC_ROOT)
As you can see, I enable admin, static and media urls. This is enough to let django's default server know where to find and serve static files (and media files too, as well as admin routes)
Yes, I can confirm that the 'right place' to store your static files for a Django deployment on Azure Web Sites is the 'static' directory in the web root.
Step 1: create a directory called static in your web root (www root)
Step 2: edit Django's settings.py and set STATIC_ROOT = 'D:/home/site/wwwroot/static'
Step 3: In your templates use the construct {% static "static_file_name" %}.

What should django settings and urls look like for media and static deploying in production with heroku?

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.

django-cms + grappelli

If anyone knows how to make django-cms play with grappelli, please give some tips
Well I've just gone through a fairly epic adventure, the story of which might be of some use to you. The end point of said adventure was getting django-cms 2.1.3 working with django-filebrowser-no-grappelli . Whilst that may sound in fact like the opposite of what you want, I ended up there because what I really wanted was to get django-cms working with filebrowser. Without grappelli though the standard django-filebrowser does not work as expected. But with grappelli django-cms does not work as expected. So therein lay the rub, to quote shakespeare. Getting django-cms working with filebrowser was relatively straight forward except for the fact that when trying to upload files with uploadify (which is shipped with filebrowser), after selecting the files in the file dialog, nothing happened. Eventually I figured out that this was because the jquery library was being loaded twice: once by filebrowser for use with uploadify, and once by django-cms. So by commenting out the second line in this file:
your site packages dir/cms/templates/cms/toolbar/toolbar.html
which loads jquery.min.js, uploadify worked as expected. Soooo...if you just want to get django-cms working with grappelli so you can use filebrowser, the above might be helpful. Here is my settings file for reference.
My solution is to implement 2 subdomains, 'www' and 'cms', in each of which a separate instance of the Django site is running with a different STATIC_ROOT and a modified INSTALLED_APPS. grappelli runs in the 'www' subdomain. It is not running in the 'cms' subdomain, so that you can use django-cms there.
Set up a subdomain: cms.example.com
Modify your webserver to serve this subdomain. Use the same settings as your main django site but point to a different script handler. e.g. if using wsgi direct the server to run wsgi_cms.py
cp wsgi.py wsgi_cms.py. Edit wsgi_cms.py and change the line
os.environ.setdefault("DJANGO_SETTINGS_MODULE", "myproject.settings")
to os.environ.setdefault("DJANGO_SETTINGS_MODULE", "myproject.settings_cms")
settings_cms.py :
:
from settings import *
INSTALLED_APPS.remove('grappelli.dashboard')
INSTALLED_APPS.remove('grappelli')
STATIC_ROOT = os.path.join('/what/ever/static_cms/')
STATIC_URL = '/static_cms/'
ADMIN_MEDIA_PREFIX = STATIC_URL + 'admin/`
modify settings.py: change INSTALLED_APPS from a tuple to a list
restart web servers
./manage.py collectstatic --settings=myproject.settings_cms
your regular site continues as normal. To edit django-cms pages with grappelli disabled go to http://cms.example.com/admin/cms/page/
I've once made a django-cms fork on github that supports grappelli, it's a bit outdated, but maybe helps you to get started or probaly you'd like to contribute.

Hosting Admin Media Locally During Development

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.