Deploying to heroku with heroku push command - python

I installed heroku plugin called heroku-push. And I deployed my app with heroku push --app appname. I have settings.py and local_settings.py and in settings.py file DEBUG is False but in local_settings.py file DEBUG is True. And I included local_settings.py in .gitignore file. When I open my page in browser there is a message telling me DEBUG=True. Say that If local_settings.py also is deployed to server, there is a code in settings.py file
try:
from .local_settings import *
except ImportError:
pass
What should I do? Heroku gives me git#heroku.com:appname.git But I can not view it or clone it. It gives me empty folder.

If you create .gitignore file (if you didn't: touch .gitignore)
Now open .gitignore with your favorite text editor and paste in the following information about files Git should ignore:
### Django ###
*.log
*.pot
*.pyc
__pycache__/
local_settings.py
I advise you to read this tutorial on medium it helped me to deploy my first django app :
https://medium.com/#BennettGarner/deploying-django-to-heroku-procfile-static-root-other-pitfalls-e7ab8b2ba33b

Related

How to deploy / migrate an existing django app / project to a production server on Heroku?

I have a basic django app (Newsdiffs)that runs just fine at localhost:8000 with python website/manage.py runserver but I'd like to migrate it to Heroku and I can't figure out what my next step is.
I thought getting it running locally would translate to running it on Heroku, but I'm realizing that python website/manage.py runserver is launching the dev settings and I'm not sure how to tell it to use the main settings.
All that is in my Procfile is this:
web: python website/manage.py runserver
Locally, that works fine, though it launches it at http://127.0.0.1:8000/ which is probably not what I want on Heroku. So how do I figure out where to set the hostname and port? I don't see either in the app anyplace.
I have just drawn this list for myself two days ago.
It was put together after having followed the steps described in Heroku's help pages for python.
It's by no means definitive nor perfect, and it will change, but it's a valid trace, since I was able to put the site online.
Some issues remain, to be checked thoroughly, e.g. the location of the media/ directory where files are uploaded should/could live outside your project for security reasons (now it works, but I have noticed if the dyno sleeps then the files are not reached/displayed by the template later).
The same goes for the staticfiles/ directory (although this one seems to work fine).
Also, you might want to set django's debug mode to false.
So here it is:
My first steps to deploy an EXISTING django application to Heroku
ASSUMPTIONS:
a) your django project is in a virtual environment already
b) you have already collected all your project's required packages with
pip freeze > requirements.txt
and committed it to git
git add requirements.txt
git commit -m 'my prj requirements'
0) Activate your project's virtual environment
workon xyz #using virtualenvwrapper
then go to your django project's directory (DPD for short) if not already taken there
cd ~/prj/xyz (or cdproject with virtualenvwrapper if setup properly)
and create a new git branch for heroku twiddling to prevent messing things up
git checkout -b he
1) Create the app on heroku
heroku create xyz
that also adds heroku as a remote of your repo
2) Add the needed packages to requirements.txt
vi requirements.txt
add
dj-database-url==0.3.0
django-postgrespool==0.3.0
gunicorn==19.3.0
psycopg2==2.6
django-toolbelt==0.0.1
static3==0.5.1
whitenoise==2.0.3
3) Install all dependencies in the local venv
pip install -r requirements.txt --allow-all-external
4) Setup the heroku django settings
cd xyz
create a copy
cp setting.py settings_heroku.py
and edit it
vi settings_heroku.py
import os
import dj_database_url
BASE_DIR = os.path.dirname(os.path.dirname(os.path.abspath(__file__)))
STATICFILES_DIRS = (os.path.join(BASE_DIR, 'static'), )
MEDIA_ROOT = os.path.join(BASE_DIR, "media")
STATIC_ROOT = os.path.join(BASE_DIR, "staticfiles")
STATIC_URL = '/static/'
MEDIA_URL = '/media/'
STATICFILES_STORAGE = 'whitenoise.django.GzipManifestStaticFilesStorage'
SECRET_KEY = os.environ["DJANGO_SECRET_KEY"]
SECURE_PROXY_SSL_HEADER = ('HTTP_X_FORWARDED_PROTO', 'https')
replace django's std db cfg with
DATABASES['default'] = dj_database_url.config()
DATABASES['default']['ENGINE'] = 'django_postgrespool'
and
WSGI_APPLICATION = 'xyz.wsgi_heroku.application'
5) Configure the necessary environment variables (heroku configs)
edit the .env file
vi .env
e.g.
DJANGO_SECRET_KEY=whatever
EMAIL_HOST_USER=youruser#gmail.com
EMAIL_HOST_PASSWORD=whateveritis
and/or set them manually if needed (in my case .env had no effect, wasn't loaded apparently, and had to set the vars manually for now)
heroku config:set DJANGO_SECRET_KEY=whatever
heroku config:set EMAIL_HOST_USER=youruser#gmail.com
heroku config:set EMAIL_HOST_PASSWORD=whateveritis
6) Create a separate wsgi file for heroku
cd xyx
cp wsgi.py wsgi_heroku.py
and edit it to make it point to the right settings
vi wsgi_heroku.py
from whitenoise.django import DjangoWhiteNoise
os.environ.setdefault("DJANGO_SETTINGS_MODULE", "xyz.settings_heroku")
application = get_wsgi_application()
application = DjangoWhiteNoise(application)
7) Make sure all the templates use
{% load staticfiles %}
8) Define the Procfile file so that it points to the right wsgi
e.g.
cd ~/prj/xyz (DPD)
vi Procfile
add
web: gunicorn xyz.wsgi_heroku --log-file -
9) Collect all static content into DPD/staticfiles/
locally, make sure django points to the right wsgi settings
export WSGI_APPLICATION=blogger.wsgi_heroku.application
python manage.py collectstatic
10) add the changes to the local git repo (he branch)
git add --all .
git commit -m 'first 4 heroku'
11) check the whole thing works locally
heroku local # in heroku's help they also add `web`, not needed?!
12) push your code to heroku
git push heroku he:master
13) make sure a instance of the app is running
heroku ps:scale web=1
14) create the tables on the heroku DB
heroku run python manage.py migrate
Note: if you see a message that says, “You just installed Django’s auth system, which means you don’t have any superusers defined. Would you like to create one now?”, type no.
15) add the superuser to the heroku DB
heroku run bash
python manage.py createsuperuser
and fill in the details, as usual
16) Populate the DB with the necessary fixtures
heroku run python manage.py loaddata yourfile.json
17) Visit the website page on heroku's webserver
heroku open
or go to
https://xyz.herokuapp.com/
and the admin
https://xyz.herokuapp.com/admin/
and the DB
https://xyz.herokuapp.com/db
Useful commands:
View the app's logs
heroku logs [--tail]
List add-ons deployed
heroku addons
and use one:
heroku addons:open <add-on-name>
Run a command on heroku (the remote env, where you are deploying)
heroku run python manage.py shell
heroku run bash
Set a config var on Heroku
heroku config:set VARNAME=whatever
View the config vars that are set (including the DB's)
heroku config
View postgres DB details
heroku pg
If you know some python and have a lot of experience building web apps in other languages but don't totally understand where Heroku fits, I highly recommend Discover Flask, which patched a lot of the holes in my understanding of how these pieces all fit together.
Some of the things that I worked out:
you really do need an isolated virtual environment if you're going to deploy to Heroku, because Heroku installs Python modules from the requirements.txt file.
Gunicorn is a web server, and you definitely need to run your app under Gunicorn or it won't run on Heroku.
The "Procfile" doesn't just give the command you use to run the app locally. And Heroku requires it. So if you've got an app that was built to run on Heroku and it doesn't include a Procfile, they left something out.
You don't tell Heroku what your hostname is. When you run heroku create it should tell you what your domain name is going to be. And every time you run git push heroku master (or whatever branch you're pushing, maybe it isn't master), Heroku will (try to) restart your app.
Heroku doesn't support sqlite. You have to run your Production DB in Postgres.
This doesn't directly answer my question, but it does fill in some of the missing pieces that were making it hard for me to even ask the right question. RTFM notwithstanding. :)

Git command when translating files in Django

I have an existing application in Django.
I want to add a translation on the page.
On page I have:
{% trans 'Projects'%}
In .po file I added:
#: templates/staff/site.html: 200
msgid "Projects"
msgid "Projekty"
Then executes the command:
django-admin.py compilemessages -l pl
After this command, I get an error:
CommandError: This Should Be Run script from the Django Git checkout or your project or app tree, or with the settings Specified module.
$ python manage.py compilemessages --settings nsp.settings
CommandError: This script should be run from the Django Git checkout or your project or app tree, or with the settings module specified.
I have got this error while I truly was inside project root folder.
The problem was, that I was running this command without python manage.py makemessages first.
The error message is misleading.
The error holds the answer, you could be running the script from anywhere so it cannot know which files to compile. Run the command from the project directory or specify the settings and you should be fine.
If you are using docker containers to build and deploy your application you should copy folder:
conf/
from root folder of your django project.
with the conf folder you should see i.e:
processing file django.po in /gamma/conf/locale/en/LC_MESSAGES
processing file django.po in /gamma/conf/locale/es/LC_MESSAGES
processing file django.po in /gamma/conf/locale/pt_BR/
without the conf folder you should see a clueless message like that:
CommandError: This script should be run from the Django Git checkout or your project or app tree, or with the settings module specified.
The error message is saying that it could not find the translations files where it expected them to be. Check that everything is correctly setup:
LOCALE_PATHS is defined in your settings.py
the files exist in the folder defined above (created by running python manage.py makemessages)
actually the error goes away even with just an empty locales folder
the compilemessages command is run from the project root folder
If you haven't set LOCALE_PATHS in your settings file, you need to do so:
import os
LOCALE_PATHS = [os.path.join(BASE_DIR, 'locale')]

Collectstatic configuration error when deploying Django app with dokku

When deploying a Django app using dokku I am getting a following error
Collectstatic configuration error. To debug, run:
$ heroku run python ./manage.py collectstatic --noinput
I found no way to run heroku run python ./manage.py collectstatic --noinput for a dokku container, but when I am trying dokku run my app python ./manage.py collectstatic --noinput, the static files are successfully copied to the STATIC_ROOT folder and no error message given.
I could solve the problem by placing collectstatic command into Procfile:
web: python manage.py collectstatic --noinput ; gunicorn myapp.wsgi
Still, I would love to know what was causing the problem and how can it be debugged. Any ideas?
You should have four settings in your settings.py file called MEDIA_ROOT, MEDIA_URL, STATIC_ROOT and STATIC_URL.
I set mine like so:
MEDIA_ROOT = 'media'
STATIC_ROOT = 'static'
MEDIA_URL = '/media'
STATIC_URL = '/static'
Inside the docker container that gets created, you will find your application under /app which makes the media path /app/media/ and the static path /app/static/.
Unfortunately if you don't have a media and static folder committed in git, it won't get created under /app automatically.
Since git doesn't allow you to commit an empty folder (it only commits files), I do the following in my projects:
mkdir media static
touch media/.dir
touch static/.dir
git add media/.dir static/.dir
git commit -m 'Make media and static directories'
The 'touch' command creates an empty file, then you 'git add' the two newly-created files and check them in.
Now when you push, the directories will be there to contain the media and static files. Just keep in mind that every time you 'git push', a new container is created, and the old one is destroyed. While this isn't a problem for your static files, your media will be lost unless you store it somewhere else.

How to deploy structured Flask app on AWS elastic beanstalk

After successfully deploying a test app using the steps outlined here:
http://docs.aws.amazon.com/elasticbeanstalk/latest/dg/create_deploy_Python_flask.html
I tried to deploy my actual flask application which has the following structure:
myApp/
runServer.py
requirements.txt
myApp/
__init__.py
helpers.py
clean.sh
static/
myApp.css
handlers/
__init__.py
views.py
templates/
layout.html
viewOne.html
viewTwo.html
Where views.py contains my url mappings.
I have tried initializing the eb instance in the root directory as well as within the myApp module and git aws.push but I get the following error on the AWS dashboard:
ERROR Your WSGIPath refers to a file that does not exist. and the application does not work (404 for any path).
How can I deploy the above Flask application to elastic beanstalk?
I encountered a similar problem deploying a Flask application to EB, with a similar directory structure, and had to do 2 things:
Update my manage.py to create an object of name application, not app
import os
from application import create_app, db
from flask.ext.script import Manager, Shell
application = create_app(os.getenv('FLASK_CONFIG') or 'default')
manager = Manager(application)
Create .ebextensions/myapp.config, and define the following block to point to manage.py
option_settings:
"aws:elasticbeanstalk:container:python":
WSGIPath: manage.py
"aws:elasticbeanstalk:container:python:staticfiles":
"/static/": "application/static/"
This let Elastic Beanstalk find the application callable correctly.
This is described briefly at the official docs, and is described in more detail in this blog post
EDIT - see project structure below
ProjectRoot
.ebextensions
application.config
application
main
forms.py
views.py
static
templates
tests
manage.py
requirements.txt
config.py
etc, etc
Add the following to .ebextensions/<env-name>.config:
option_settings:
"aws:elasticbeanstalk:container:python":
WSGIPath: myApp/handlers/views.py
Update:
If you don't have .ebextensions directory, please create one for the project. You can find more information of what can be done regarding the container configuration in Customizing and Configuring AWS Elastic Beanstalk Environments guide.
Your WSGIPath refers to a file that does not exist.
This error appears because Beanstalk, by default, looks for application.py. Check at Beanstalk web UI, Configuration > Software Configuration, WSGIPath is mapped to application.py
Update the WSGIPath as shown in the previous replies or rename to application.py file.
As of awsebcli 3.0, you can actually edit your configuration settings to represent your WSGI path via eb config. The config command will then pull (and open it in your default command line text editor, i.e nano) an editable config based on your current configuration settings. You'll then search for WSGI and update it's path that way. After saving the file and exiting, your WSGI path will be updated automatically.
WSGI configuration was painful for me. I did changed WSCI settings using eb config command but it did not work. Below you can fix this in 5 easy steps.
1- Moved app.py function to the root of the directory (where I runned eb init command.
2- Also renamed app.py as application.py and in that initilized application as application = Flask(__name__) not app = Flask(__name__)
3- eb deploy did not worked after this (in the same project) I tried to fix config by using eb config but it was too hairy to sort it out. Delete all .extensions, .gitignore etc from your project.
4- re initialize your project on EB with eb init and follow the prompts. when deployment is done, eb open would launch your webapp (hopefully!)
When I encountered this problem it was because I was using the GUI to upload a zip of my project files. Initially I was zipping the project level directory and uploading that zip to EB.
Then I switched to simply uploading a zip of the project files themselves-ie select all files and send those to a zip-and then the GUI upload utility was able to find my application.py file without a problem because the application.py file was not in a subfolder.
Well, In my case I followed the entire process and conventions but was still getting 404. The problem was my virtual environment. I was ignoring all environment config related folders/files in my .gitignore but not in .ebignore. After creating .ebignore and ignoring all the folders/files which were not related to project code, fixed the issue.

Multiple settings files with Google App Engine project

A note before the question
We generally have a settings.py file and a local_settings.py file in standard Django project layouts.
settings.py: for production settings
local_settings.py: for local settings that override production settings when running the project locally
The local_settings.py file is added to .gitignore to avoid being pushed into production via git push.
The question
In appengine when we push the application using:
appcfg.py update exampleproject
The local_settings.py file also gets pushed up even though it has been added to .gitignore.
At first adding the following lines to app.yaml looks like a possible solution:
skip_files:
- ^(.*/)?local_settings.py
These lines tell app engine to ignore the local_settings.py file.
But, then we face another problem ->
The local_settings.py file is totally excluded. ie. It is not even used when running the application locally along with dev_appserver.py.
Is there any good solution that can help define multiple settings files in a Google App Engine based Django project?

Categories