I am trying to deploy my django app on heroku. All the static files are served by whitenoise and are migrated successfully. But how do I get my media files that are uploaded using ImageField to display during production.
my settings.py
STATIC_URL = '/static/'
STATIC_ROOT = 'C:/Users/Sak/mpro/feat/static/'
STATICFILES_STORAGE = 'whitenoise.django.GzipManifestStaticFilesStorage'
MEDIA_URL = '/media/'
MEDIA_ROOT = os.path.join(BASE_DIR, "media")
wsgi.py
import os
from django.core.wsgi import get_wsgi_application
os.environ.setdefault("DJANGO_SETTINGS_MODULE", "mpro.settings")
application = get_wsgi_application()
try:
from django.core.wsgi import get_wsgi_application
from whitenoise.django import DjangoWhiteNoise
application = get_wsgi_application()
application = DjangoWhiteNoise(application)
from dj_static import Cling
application = Cling(get_wsgi_application())
except:
pass
urls.py
urlpatterns = [
url(r'^', include('feat.urls', namespace="feat")),
url(r'^admin/', include(admin.site.urls)),
] + static(settings.MEDIA_URL, document_root=settings.MEDIA_ROOT)
All my media files are uploaded to base_dir/media/media and when whitenoise collects static files it only collects files at STATIC_ROOT, so how do I get my media files deployed. When I run heroku run ls I can see the folder media.
So, first of all it's important to realise that if you have a bunch of files that are part of your project (including things like images and such) and are deployed along with it, they are more likely to be static files than media files in Django parlance.
Media files in Django are for runtime uploaded files. They will generally be stored with a corresponding db entry such as models.ImageField(upload_to='/photos') but that isn't necessarily so.
Your media setup is wrong for Heroku, as you shouldn't be writing to a directory on the server anyway (this is what you are telling Django to do with MEDIA_ROOT = os.path.join(BASE_DIR, "media").
Most commonly you would instead use an S3 bucket for media on Heroku. This is a fairly comprehensive explanation of that. You can probably skip the bit about CORS and go for open permissions on the bucket (depending on your use case). The important bits are:
# settings.py
# Tell django what URL to server your media from
MEDIA_URL = "https://%s/" % AWS_S3_CUSTOM_DOMAIN
# Tell Django to use the boto storage backend to save media files.
DEFAULT_FILE_STORAGE = 'storages.backends.s3boto.S3BotoStorage'
If you want to use S3 for static AND media storage, the link explains that too.
You might want to look at this repo for a pretty comprehensive run-down of the AWS settings and what they do, plus a nicely wrapped package to do some of it for you.
More generally I found Django Herokuify exceptionally useful for all the boilerplate on Heroku.
Related
Since I had started Django, I'm tackling some ridiculous problems. Recently, when I start a new project and I run it on the server, Django's admin CSS is not loaded. The last project I ran on the server, after a while it was okay, and the real Django admin template was there and the CSS was loaded and it was working. But this time again the same problem happened and I don't know how to solve it cause the project here is the photo is raw, with no special code.
I don't know if it's Chrome problem or not, but I have tried it on other browsers and it was the same thing.
I would be glad if you can help me
the answer I found was to change STATIC_URL = 'static/' in settings.py to STATIC_URL = '/static/'. Only one '/' may change your whole admin appearance. This problem may not happens to everyone but running code in Pycharm, I had been tackling it for such a long time.
If this problem is happening locally, then just change your settings.py
DEBUG = True
#...
#...
STATIC_ROOT = YOUR_STATIC_ROOT_DIRECTORY
Then run collectstatic, make sure you have a proper STATIC_ROOT directory which is also in your settings.py file
python manage.py collectstatic
If you have deployed your app on a production server then, you have to follow certain things in order to get stylesheet and javascript files.
Firstly
In your urls.py you need to add this code
urlpatterns += static(settings.MEDIA_URL, document_root=settings.MEDIA_ROOT) + \
static(settings.STATIC_URL, document_root=settings.STATIC_ROOT)
Then you have to use a third-party media file server(CDN) Like AWS S3 or you can serve your css, js or media files from your Django server
If you don't want to use AWS S3, then you can either send css/js using your django app (which is not ideal to do), or you can use nginx or apachee to send your css/js
For Nginx to send js/css
You have to add a Static and Media File Root that can be accessed by your django application, I usually use /var/www/ to serve static and media from any Linux server
STATIC_ROOT = '/var/www/static'
MEDIA_ROOT = 'var/www/media'
Then if you are using nginx
server {
server_name domainname.com;
access_log off;
location /static/ {
root /var/www/static;
}
location /media/ {
root /var/www/media;
}
If it is still not working, then your django app might not be able to use the given static_root and media directory, make sure your app has access to them
If you want to send your js/css from your django app (Better not to do in production)
Then
To install whitenoise
pip install whitenoise
In your settings file
MIDDLEWARE = [
'django.middleware.security.SecurityMiddleware',
'whitenoise.middleware.WhiteNoiseMiddleware',
# ...
]
In Django 2.2, when I have DEBUG=True, all my static files render fine. But when I set DEBUG=False to test my production settings, all static file URLs suddenly return 404 errors.
I have a project structure like:
myproject/
myproject/
settings.py
urls.py
manage.py
static/
thumbnails/
image.png
My relevant static settings in settings.py:
STATIC_ROOT = os.path.abspath(os.path.join(os.path.dirname(__file__), '..', '..', 'static'))
INSTALLED_APPS = [
'django.contrib.admin',
'django.contrib.auth',
'django.contrib.contenttypes',
'django.contrib.sessions',
'django.contrib.messages',
'django.contrib.staticfiles',
]
STATICFILES_FINDERS = (
'django.contrib.staticfiles.finders.FileSystemFinder',
'django.contrib.staticfiles.finders.AppDirectoriesFinder',
)
ROOT_URLCONF = 'myproject.urls'
STATIC_URL = '/static/'
DEBUG = False
And my urls.py looks like:
import os
from django.contrib import admin
from django.conf.urls.static import static
from django.conf import settings
urlpatterns = [
path('admin/', admin.site.urls),
]
urlpatterns += static(settings.STATIC_URL, document_root=settings.STATIC_ROOT)
Why does a url like http://localhost:8000/static/thumbnails/image.png work fine when debug is on, but return a 404 when debug is off?
In production, you should run python manage.py collectstatic, and actually serve your static files from somewhere.
If you look at the docs for static files, you'll see
Serving the files
In addition to these configuration steps, you’ll also need to actually
serve the static files.
During development, if you use django.contrib.staticfiles, this will
be done automatically by runserver when DEBUG is set to True (see
django.contrib.staticfiles.views.serve()).
This method is grossly inefficient and probably insecure, so it is
unsuitable for production.
See Deploying static files for proper strategies to serve static files
in production environments.
You should set the STATIC_ROOT in you production settings to a folder on you web server, and configure your webserver to point your STATIC_URL to that folder. See here.
In your case, it's seems you have taken all these steps, except actually serving your static files. You can do this by pointing your web server to the correct folder, or serving you static files from a CDN or other solution. Here's how to do it using apache
Django was never meant to replace web servers. From the Django docs:
Django doesn’t serve files itself; it leaves that job to whichever Web server you choose.
This method is grossly inefficient and probably insecure, so it is unsuitable for production.
On localhost with DEBUG = TRUE it deploys the static file. While on production, you should use your web server(Apache, 'Nginx' etc) to deploy static files.
Just list the static directory in the configuration file of your web server. More detailed instructions regarding deployment can be found here
I'm trying to push my Django project to Heroku, but it isn't loading the staticfiles.
I used this to setup the things, everything is fine but I'm not able to fix the issue with static files.
My directory structure is like this
help_the_needy
help_the_needy
__init__.py
settings.py
urls.py
views.py
wsgi.py
manage.py
Procfile
requirements.txt
static
css
font-awesome
fonts
img
js
templates
base.html
display_list2.html
index.html
Here is the complete code (all files).
This is my settings.py.
I tried alot of things to fix this, but nothing seems to work.
When I push it does copy static files but it's not loading them.
Can someone please point me to my mistake? Where is it wrong?
I have been dealing with the same problem too. And here are the 2 things that I changed in my code.
(I'm using Django 1.7)
1) settings.py
I add these lines to the setting files
BASE_DIR = os.path.dirname(os.path.dirname(__file__))
STATIC_ROOT = os.path.join(BASE_DIR, 'staticfiles')
STATICFILES_STORAGE = 'whitenoise.django.GzipManifestStaticFilesStorage'
TEMPLATE_DIRS = (
os.path.join(BASE_DIR, 'templates'),
# Add to this list all the locations containing your static files
)
STATIC_ROOT: this tells Django where to (a) put the static files when you run python manage.py collectstatic and (b) find the static files when you run the application
TEMPLATE_DIRS: this tells Django where to look for your static files when it search for statics files when you run python manage.py collectstatic
2) wsgi.py
Originally my file was:
import os
os.environ.setdefault("DJANGO_SETTINGS_MODULE", "xxxx.settings")
from django.core.wsgi import get_wsgi_application
application = get_wsgi_application()
And I changed it to:
import os
os.environ.setdefault("DJANGO_SETTINGS_MODULE", "xxxx.settings")
from django.core.wsgi import get_wsgi_application
from whitenoise.django import DjangoWhiteNoise
application = get_wsgi_application()
application = DjangoWhiteNoise(application)
Read here for more information on whitenoise: https://devcenter.heroku.com/articles/django-assets#whitenoise
Also, remember to install whitenoise:
pip install whitenoise==2.0.6
Before deploying the project, run:
python manage.py collectstatic
This will create a folder indicated by STATIC_ROOT (declared in your settings.py), containing all your static files.
Since it's been a few years since this was posted (and it still pops up when I search for the issue), here's what worked for me in Django 3.2.
pip install whitenoise
Make sure in settings.py you have
STATIC_ROOT = os.path.join(BASE_DIR, 'staticfiles')
STATIC_URL = '/static/'
# Extra places for collectstatic to find static files.
STATICFILES_DIRS = (
os.path.join(BASE_DIR, 'static'),
)
Add whitenoise to your Middleware:
MIDDLEWARE = [
'whitenoise.middleware.WhiteNoiseMiddleware',
]
Make sure the directory you specified as the STATIC_ROOT (staticfiles) exists in your base directory and is not empty.
After that, I committed the changes and Heroku was able to build the static files and everything worked fine.
pip install whitenoise
Add whitenoise to requirement.txt.
and also add whitenoise in the middleware of settings.py
MIDDLEWARE = [
'django.middleware.security.SecurityMiddleware',
'whitenoise.middleware.WhiteNoiseMiddleware', #add whitenoise
'django.contrib.sessions.middleware.SessionMiddleware',
'django.middleware.common.CommonMiddleware',
'django.middleware.csrf.CsrfViewMiddleware',
'django.contrib.auth.middleware.AuthenticationMiddleware',
'django.contrib.messages.middleware.MessageMiddleware',
'django.middleware.clickjacking.XFrameOptionsMiddleware',
]
Follow the steps in https://devcenter.heroku.com/articles/django-assets
Your STATICFILES_DIRS setting is wrong. It should be pointing to the actual location of the "static" directory containing the files:
STATICFILES_DIRS = (
os.path.join(BASE_DIR, 'static'),
)
It looks like django don't know where your static_root is.
This folder is autogenerated when you fire manage.py collectstatic
Make sure that the folders static and templates are inside your django app. You didn't created a django app to put this folders into. You created a django project the next step is to create a django app with something like this python manage.py startapp polls
# Absolute filesystem path to the Django project directory:
DJANGO_ROOT = dirname(dirname(abspath(__file__)))
# Absolute filesystem path to the top-level project folder:
SITE_ROOT = dirname(DJANGO_ROOT)
STATIC_URL = '/static/'
STATIC_ROOT = normpath(join(SITE_ROOT, 'static_root'))
Your urls.py file lacks the setting to manage and route requests for static resources.
in order to provide access to static resorces you must add to urlpatterns of urls.py:
urlpatterns += patterns('',
(r'^static/(?P<path>.*)$', 'django.views.static.serve', {'document_root': settings.STATIC_ROOT}),
)
What are the differences of these three static url?
I am not sure if I am right, I am using the MEDIA_ROOT to store my uploaded photos (via models.ImageField())
However, I created a JS script to my admin and in admin.py. I defined the media as below:
....
class Media:
js = ('/admin/custom.js', )
and my settings.py:
....
STATIC_ROOT = "/home/user/project/django1/top/listing/static"
and I added the custom.js to STATIC_ROOT/admin/custom.js, but it is not working. Throwing 404 not found error.
And then I change the STATIC_ROOT to STATICFILES_DIRS, and it works!!
....
STATICFILES_DIRS = "/home/user/project/django1/top/listing/static"
So, I am not understand what is going on here. In fact, I just don't understand what is the difference between STATIC_ROOT and STATICFILES_DIRS.
Currently I am testing Django in my machine via virtualenv, not deployed yet, is it the reason STATIC_ROOT not working??
Development
STATIC_ROOT is useless during development, it's only required for deployment.
While in development, STATIC_ROOT does nothing. You don't even need to set it. Django looks for static files inside each app's directory (myProject/appName/static) and serves them automatically.
This is the magic done by manage.py runserver when DEBUG=True.
Deployment
When your project goes live, things differ. Most likely you will serve dynamic content using Django and static files will be served by Nginx. Why? Because Nginx is incredibly efficient and will reduce the workload off Django.
This is where STATIC_ROOT becomes handy, as Nginx doesn't know anything about your Django project and doesn't know where to find static files.
So you set STATIC_ROOT = '/some/folder/' and tell Nginx to look for static files in /some/folder/. Then you run manage.py collectstatic and Django will copy static files from all the apps you have to /some/folder/.
Extra directories for static files
STATICFILES_DIRS is used to include additional directories for collectstatic to look for. For example, by default, Django doesn't recognize /myProject/static/. So you can include it yourself.
Example
STATIC_URL = '/static/'
if not DEBUG:
STATIC_ROOT = '/home/django/www-data/example.com/static/'
STATICFILES_DIRS = [
os.path.join(BASE_DIR, 'static/'),
]
You can find these settings in the Django documentation. Here are my own definitions and quotations from the documentation:
MEDIA_ROOT is the folder where files uploaded using FileField will go.
Absolute filesystem path to the directory that will hold user-uploaded files.
STATIC_ROOT is the folder where static files will be stored after using manage.py collectstatic
The absolute path to the directory where collectstatic will collect static files for deployment.
If the staticfiles contrib app is enabled (default) the collectstatic management command will collect static files into this directory. See the howto on managing static files for more details about usage.
STATICFILES_DIRS is the list of folders where Django will search for additional static files aside from the static folder of each app installed.
This setting defines the additional locations the staticfiles app will traverse if the FileSystemFinder finder is enabled, e.g. if you use the collectstatic or findstatic management command or use the static file serving view.
In your settings, you should have:
MEDIA_ROOT = os.path.join(BASE_DIR, "media/")
STATIC_ROOT = os.path.join(BASE_DIR, "static/")
# Make a tuple of strings instead of a string
STATICFILES_DIRS = ("/home/user/project/django1/top/listing/static", )
...where:
BASE_DIR = os.path.dirname(os.path.dirname(os.path.abspath(__file__)))
as defined in the default Django settings.py now.
Difference between STATICFILES_DIRS and STATIC_ROOT
The STATICFILES_DIRS can contain other directories (not necessarily app directories) with static files and these static files will be collected into your STATIC_ROOT when you run collectstatic. These static files will then be served by your web server and they will be served from your STATIC_ROOT.
If you have files currently in your STATIC_ROOT that you wish to serve then you need to move these to a different directory and put that other directory in STATICFILES_DIRS. Your STATIC_ROOT directory should be empty and all static files should be collected into that directory.
MEDIA_ROOT where media files ,all uploaded files goes.
Example : Images, Files
class Media:
js = ('/admin/custom.js', )
but it is not working. Throwing 404 not found error.
The 404 error is in part because of the leading slash in the file path.
I'm using the new django-rest-framework 2.0 and have been following the tutorial for creating a rest based API. The API is now complete, however I am having trouble getting the bootstrap resources to load, all return with a 404 Not Found from Django.
I feel like the resources should be loaded from django-rest-framework module's static directory, And when I do a listing on 'python2.7/dist-packages/rest_framework/static/rest_framework' I see the css, js, and img directories I need with but I have been unable to find any place in the documentation that shows how to link the CSS from the module to my project.
What is the best course of action here? Should I download the source and copy the folder into my /static directory? Symlinking is out of the question because I need to check the project into a central repo.. Ideas?
First up, I'm assuming that you mean the bootstrap static resources aren't loading for the browsable API? (Although I guess it could be that you're trying to use them elsewhere in your project?)
If you're running with DEBUG=True they should be served automatically, but once you're running with DEBUG=False you need to make sure to run manage.py collectstatic and ensure your STATIC_ROOT and STATIC_URL settings are correct.
Django's static files documentation should help: https://docs.djangoproject.com/en/dev/howto/static-files/
If you're still not having any luck I'd suggest you double check your Django version (1.3 and upwards is supported), and REST framework version (Anything from version 2 onwards), and make sure you step through the tutorial step-by-step, taking care particularly with the project setup.
If you're using Heroku you'll want to make sure you are using the configurations in the getting started documentation (https://devcenter.heroku.com/articles/getting-started-with-django). See the section "settings.py" and "wsgi.py". I was having the same problem and this solved it.
settings.py
import os
BASE_DIR = os.path.dirname(os.path.abspath(__file__))
STATIC_ROOT = 'staticfiles'
STATIC_URL = '/static/'
STATICFILES_DIRS = (
os.path.join(BASE_DIR, 'static'),
)
wsgi.py
from django.core.wsgi import get_wsgi_application
from dj_static import Cling
application = Cling(get_wsgi_application())
CSS is not found. The fix would be to make the missing css files (404 for files seen in the browser console) available. That's it.
You can make the css files accessible in backend(need some tweaks) or in front end(comparatively easy).
This solution works perfect if you have a seperate frontend & backend(restful) setup such as Django-Django rest framework and AngularJS..
Let us say if django backend is running at 8000, and front end is running at 9000.
frontend.example.com loads front end JS app running at 9000
backend.example.com loads django app running at 8000
in settings.py
import os
BASE_DIR = os.path.dirname(os.path.dirname(__file__))
STATIC_URL = 'http://frontend.example.com/static/'
STATIC_ROOT = os.path.join(BASE_DIR, 'static')
then in terminal
$ python manage.py collectstatic
Then go to dir where you have the folder static
$ cp -rf static/* /frontend-code-directory/static/
DONE.
What I have done basically, is copying all css of django apps to the frontend. Frontend serves this easy as frontend is already a collection of static files.