Collectstatic deleting wagtail blog images - django

I have a wagtail site that I deploy using elasticbeanstalk. When I deploy collectstatic is ran:
.platform/hooks/postdeploy
#!/bin/sh
source /var/app/venv/staging-LQM1lest/bin/activate
python /var/app/current/manage.py migrate
python /var/app/current/manage.py createsu
python /var/app/current/manage.py collectstatic --noinput
I have found that this has the effect of deleting any images that are in my blog posts. I assume this is because the blog posts have been made using the page editor (of the deployed site) and are not on my local machine like the rest of the static files
How should I be setting things so that I do not delete the images everytime collectstatic is ran?

Make sure the MEDIA_ROOT and MEDIA_URL settings in your project (which define where uploaded files will be placed) are set to something different to STATIC_ROOT and STATIC_URL (which define the location of static files that are deployed as part of the app).

Related

whitenoise not adding random string

I just put up another copy of my Django app in production. The only intended difference between my "old" app and the "new" one is that the old app runs in "traditional" Heroku, and the new app runs in "Dockerized" Heroku.
The weirdest thing is happening. I use Whitenoise to serve my static assets. On the older app, links to my static assets look like this in the generated pages:
<link href="/static/assets/css/bootstrap.min.9f236e18d5bf.css" rel="stylesheet">
But on my new app, that little string (9f236e18d5bf) is missing. it looks like:
<link href="/static/assets/css/bootstrap.min.css" rel="stylesheet">
As a result, I don't have any stylesheets on my new site.
Is there an additional step that I have to take in the Dockerized version to get this to work? Or am I missing some combination of STATIC* settings values that are needed.
My temporary workaround was to add python manage.py collectstatic --noinput to Dockerfile.web, and then set:
STATICFILES_STORAGE = 'django.contrib.staticfiles.storage.StaticFilesStorage'
Which works, but I'm wondering if I'm going to get a scaling issue on Monday.
It looks the answer comes in two parts, and I had one of each working at different times.
Be sure to have this in your Dockerfile.web:
RUN python manage.py collectstatic --noinput
CMD CMD gunicorn --bind 0.0.0.0:8000 <project-name>.wsgi
Note that you want to use RUN for your collectstatic command. Apparently only the last CMD value in a Dockerfile makes any sense.
In settings.py, have
STATICFILES_STORAGE = 'whitenoise.storage.CompressedManifestStaticFilesStorage'
That setting will cause collectstatic to add the hashes to the names of each file that is copied into the directory specified in STATICFILES_ROOT.

Why won't newly installed Django app with NGINX serve static assets properly?

I have a Mac running OS X 10.9.3. I am trying to setup a Django application backed by a PostgreSQL database served by gunicorn, with static assets served by NGINX. I'm an old hand at Django with MySQL running with the developement server (manage.py runserver). But I'm new to setting it up with virtualenv, gunicorn and NGINX. So I'm following the instructions here.
My Django Project is being served successfully at localhost:3026. As a test of the database connectivity, I wanted to take a look at the Django Admin interface. I visited localhost:3026/admin/
I have included a screenshot below.
Why does this admin page look so ugly? It lacks the neccessary graphical interface and css that it is supposed to have? It looks like NGINX is not properly serving up those static assets. How can I troubleshoot and fix this issue?
EDIT:
After I posted this question, I did python manage.py collectstatic. That went and successfully copied all the static files to where they were supposed to (I think?) live in /opt/myenv/static. You can see the output of that command here. I then re-started gunicorn and nginx. I thought that would fix it. But unfortunately it didn't. The issue remains. In my Django settings.py file, I have configured the STATIC variables as follows:
STATIC_ROOT = "/opt/myenv/static/"
STATIC_URL = '/static/'
Try run command,
python manage.py collectstatic
If the commands executes successfuly, the static file would be generated in your project path, and then if you config the right static path, the web page will be correct.

Why isn't collectstatic being run automatically when I deploy my Django app to Heroku?

I've followed the official Heroku docs on Django and Static Assets; I've installed dj-static and added it to my requirements.txt file, properly configured all the variables in my settings.py file:
STATIC_ROOT = os.path.join(CONFIG_ROOT, 'served/static/')
STATIC_URL = '/static/'
STATICFILES_DIRS = (
os.path.join(CONFIG_ROOT, 'static'),
)
And this is what my wsgi.py looks like:
import os
os.environ.setdefault("DJANGO_SETTINGS_MODULE", "my_django_project.settings")
from django.core.wsgi import get_wsgi_application
from dj_static import Cling
application = Cling(get_wsgi_application())
The contents of Procfile:
web: gunicorn --bind 0.0.0.0:$PORT my_django_project.wsgi:application
In the docs, it says that "collectstatic is run automatically when it is configured properly." But when I navigate to my site there's clearly no css.
I've tried debugging using heroku run, but that just copies the static files as expected.
I've noticed that when I include the collectstatic command in my Procfile, i.e.
web: python my_django_project/manage.py collectstatic --noinput ; gunicorn -b 0.0.0.0:$PORT my_django_project.wsgi:application
...that works as expected, and the static files are served.
However what's strange about that is when I run heroku run bash and look inside the directory that STATIC_ROOT is pointing to, there's nothing there! In fact, the entire served/ directory is missing, and yet, the static files are still being served!
I'd still like to know why isn't collectstatic being run automatically though -- like mentioned in the docs -- when I deploy my Django app to Heroku.
It looks like you might be using a specific settings module for Heroku/production. Further, you've set the environment variable DJANGO_SETTINGS_MODULE to point to this settings module (and that way, when the app runs, Django knows to use that one and not, say, your default/development one). Finally, you've probably configured static asset settings in Heroku/production settings module (perhaps, STATIC_ROOT).
Okay, so if this is all correct, then here is the issue: heroku environment variables are only set at serve-time, not at compile-time. This is important because collectstatic is a compile-time operation for Heroku. (Heroku goes through 2 stages when you push: 1) compiling, which involves setting the application up (collectstatic, syncdb, etc) 2) serving, the normal operation of your application).
So, essentially, you've done everything correctly, but Heroku hasn't exposed your environment variables, including your specification of a different settings module, to collectstatic.
To have your environment variables set to compile-time, enable Heroku's user-env-compile lab feature like this:
heroku labs:enable user-env-compile
I think this is a silly thing to do by default, and would be interested in hearing why Heroku thought it was a good idea.
Have you tried adding the user_env_compile setting to your heroku config?
heroku labs:enable user-env-compile
With that enabled collectstatic should be run whenever you deploy to heroku automatically.
I am using the heroku python buildpack with dokku, and collectstatic was not being run because it had no execute permission. They fixed that in a recent commit (Dec 13, 2013), so it should work now.

Can't find static files for the Django admin interface

I can't find an answer to what seems like a simple question.
I have a Django 1.5 app on Heroku using staticfiles. The static files defined within my app can be found fine:
$ heroku run python manage.py findstatic bootstrap.min.css
Running `python manage.py findstatic bootstrap.min.css` attached to terminal... up, run.5557
Found 'bootstrap.min.css' here:
/app/myapp/static/bootstrap.min.css
But the static files for the built-in admin interface can't be found, e.g.
$ heroku run python manage.py findstatic base.css
Running `python manage.py findstatic base.css` attached to terminal... up, run.4546
No matching file found for 'base.css'.
The relevant bit of my settings is, I guess, this:
STATICFILES_FINDERS = (
'django.contrib.staticfiles.finders.FileSystemFinder',
'django.contrib.staticfiles.finders.AppDirectoriesFinder',
)
For clarity, everything else on the admin interface works, but not the static CSS files. If I visit the admin login page, the server logs have:
No such file or directory: 'staticfiles/admin/css/base.css'
No such file or directory: 'staticfiles/admin/css/login.css'

Using collectstatic with multiple environments

I have a Django app on Heroku, with staging and production environments. Static files are hosted on S3. I'm streamlining my deployment process and plan to set up fabfiles once I have things working manually.
How can I configure collectstatic to push to multiple places? If I run it locally, it uses my dev settings (with a local STATIC_ROOT). If I run it on one of my Heroku apps (heroku run ./manage.py collectstatic), then it can't grab the files (since .slugignore ensures they're never pushed to Heroku). The same applies if I include collectstatic in my Procfile.
I'm also using django-pipeline, though it's not yet doing much since I'm stuck on the collectstatic bit.
UPDATE
In response to Marat's question, I tried passing a settings file as an option to collectstatic: ./manage.py collectstatic --settings=project.settings.prod, but got an error: Unknown command: 'collectstatic' I checked on the server though and Installed Apps does include django.contrib.staticfiles and I can also run collectstatic remotely, so I'm not sure what would cause that.
You can set the environment variable DJANGO_SETTINGS_MODULE so you don't need specify --settings everywhere:
heroku config:set DJANGO_SETTINGS_MODULE=project.settings.prod
First, if you are going to serve static via CloudFront, you can use custom origin and always use local STATIC_ROOT. Actually it has some advantages over S3 source, eg gzip support.
Another good thing you can do is to have environment dependent settings in a separate file and then import it in settings.py, eg:
local_settings.py (not in project repository, yet you can have local_settings.py.example):
#environment dependent settings
DATABASES = { .. }
CACHES = { .. }
STATIC_ROOT = 'your_path/static'
settings.py:
import local_settings
I've just replied a similar question on Upload Media from Heroku to Amazon S3. If you customise your settings to take in account environmental vars, you can use filesystem storage backends locally and S3 storage backends when pushing to Heroku. This will collect and upload your static files when your slug is compiled.