heroku buildpack for python/geos - django

I am running my django app on heroku. I want to use their websolr plugin to add spatial search to the app via django haystack.
Spatial serach in django haystack depends on the GEOS C library that is not deployed on heroku by default.
So in order to use spatial search I followed https://devcenter.heroku.com/articles/buildpack-binaries to create a binary package of GEOS.
To deploy the binaries I forked the heroku buildback for python and modified bin/compile to include:
AWESOME_VM_BINARY="http://vulcan-dtornow.herokuapp.com/output/05391114-f314-4aa7-9aab-bc09025d4898"
mkdir -p /app/.heroku/vendor/geos
curl $AWESOME_VM_BINARY -o - | tar -xz -C /app/.heroku/vendor/geos -f -
I added the custom build pack to my application, redeployed but still I cannot access the library. When I run ls the geos folder does not show up
heroku run ls /app/.heroku/vendor
Any idea what I am missing? Thanks for your help!

Another option is using a buildpack that only contains the geospatial libraries and combine it with the python buildpack. This is a cleaner separation:
https://github.com/cyberdelia/heroku-geo-buildpack/
in combination with
https://github.com/heroku/heroku-buildpack-multi
To use it add a .buildpacks file to your repo that looks something like this
https://github.com/cyberdelia/heroku-geo-buildpack.git
https://github.com/heroku/heroku-buildpack-python.git
(the use of multi buildpacks is explained in the multi buildpack repo as well)

You should be able to use the GeoDjango buildpack that was already created here

Related

heroku PostGIS syncdb error

I am having trouble getting a simple GeoDjango app running on heroku. I have created the postgis extension for my database but I am not able to run syncdb without getting the following error:
from django.contrib.gis.geometry.backend import Geometry
File "/app/.heroku/python/lib/python2.7/site-packages/django/contrib/gis/geometry/backend/__init__.py", line 14, in <module>
'"%s".' % geom_backend)
django.core.exceptions.ImproperlyConfigured: Could not import user-defined GEOMETRY_BACKEND "geos".
Any ideas what I am doing wrong? Also does anyone know of a tutorial for getting a simple geodjango project running on heroku? Thanks for your help
I ran into this same issue and Joe is correct, you are missing a buildpack. What I did differently was include both the heroku-geo-buildpack and the heroku-buildpack-python. Both can be included by using the heroku-buildpack-multi and adding a ".buildpacks" file to your home directory in which to include the other buildpacks.
https://github.com/ddollar/heroku-buildpack-multi
So set buildpack-multi as your buildpack and add a .buildpacks file in your project base directory:
$ heroku config:set BUILDPACK_URL=https://github.com/ddollar/heroku-buildpack-multi.git
$ touch .buildpacks
# .buildpacks
https://github.com/cyberdelia/heroku-geo-buildpack.git#1.0
https://github.com/heroku/heroku-buildpack-python
When you push this, Heroku will install the software packages required to run python (python, pip, etc), along with the software packages required to run postgis (geos, proj and gdal).
I gave heroku-buildpack-geodjango a try but I believe it might be out of date (hasn't been updated in a year).
I just ran into the exact same error after using the multi buildpack method from ddollar https://github.com/ddollar/heroku-buildpack-multi with no problems up until this morning. As Jeff writes, you just point your buildpack at the multi and then add a .buildpacks file.
$ heroku config:set BUILDPACK_URL=https://github.com/ddollar/heroku-buildpack-multi.git
$ cat .buildpacks
# .buildpacks
https://github.com/cyberdelia/heroku-geo-buildpack.git
https://github.com/heroku/heroku-buildpack-python
Also dont forget to add django.contrib.gis to the apps in settings.
Everything should go well and install the geos and gdal libs when you push to heroku but you will find that django doesnt find them and you get the error. This is because django wants the full path as per the docs:
https://docs.djangoproject.com/en/dev/ref/contrib/gis/install/geolibs/
So add this to settings.py:
GEOS_LIBRARY_PATH = "{}/libgeos_c.so".format(environ.get('GEOS_LIBRARY_PATH'))
GDAL_LIBRARY_PATH = "{}/libgdal.so".format(environ.get('GDAL_LIBRARY_PATH'))
It seems like you are missing some C libraries. Consider the GeoDjango Heroku buildpack:
https://github.com/cirlabs/heroku-buildpack-geodjango/
heroku create --stack cedar --buildpack http://github.com/cirlabs/heroku-buildpack-geodjango/
git push heroku master
The required libraries should be installed automatically using these commands.

Installing a gem bundle in a python app on Heroku

I have a Python app on Heroku running with Django. The app launches and works perfectly. The first couple lines of a push look like this:
(venv)➜ djangoproject git:(development) ✗ git push
Counting objects: 33, done.
Delta compression using up to 4 threads.
Compressing objects: 100% (21/21), done.
Writing objects: 100% (21/21), 1.96 KiB, done.
Total 21 (delta 15), reused 0 (delta 0)
-----> Heroku receiving push
-----> Python/Django app detected
...
I need to install a gem program on the dyno (specifically, Compass).
Heroku's instructions are to provide a Gemfile and Gemfile.lock in the root directory with the required gems. As soon as I provide this, however, Heroku thinks the app is a Ruby app:
(venv)➜ djangoproject git:(development) ✗ git push
Counting objects: 33, done.
Delta compression using up to 4 threads.
Compressing objects: 100% (21/21), done.
Writing objects: 100% (21/21), 1.96 KiB, done.
Total 21 (delta 15), reused 0 (delta 0)
-----> Heroku receiving push
-----> Ruby app detected (NOTE: this is paraphrased)
...
Is there any way I can install a ruby gem while running the site as a Python/Django app?
Try explicitly selecting the python buildpack by using heroku config:add BUILDPACK_URL=https://github.com/heroku/heroku-buildpack-python.git
It will still perform the detection process but I think (?) it will run the buildpack you've explicitly selected before or instead of attempting any others, and since you still have a python application installed, it should work.
Note that after you do the config:add you need to rebuild your slug on Heroku, which currently can ONLY be done by pushing an actual code change via git. You can make an empty git commit if you don't have any real changes to push, using git commit --allow-empty -m "Empty commit"
You can also create a new project using the --buildpack command line option.
I ran into the same problem and this worked for me:
https://github.com/ddollar/heroku-buildpack-multi
How it works:
You explicitly tell Heroku that you want to use this "multi" buildpack using the "heroku config:add BUILDPACK_URL=..." command
You create a .buildpacks file in your root directory that simply lists the git URLs for the various buildpacks you want to use. I used the python and ruby buildpacks.
git push to Heroku and watch all buildpacks get used
It's also worth mentioning that the python buildpack has a couple of hooks that you can use to do additional custom work. If you create a bin/pre_compile file or a bin/post_compile file then those scripts will be called by the python buildpack just before/after the main compile step. So you could also use these hooks to get Ruby or other dependencies installed. But IMO it's easier to let Ruby's own buildpack install the Ruby dependencies.
You need to use custom buildpack that allows you to build both ruby and python dependencies.
heroku config:add BUILDPACK_URL=https://github.com/mandest/heroku-buildpack-rubypython
Add a Gemfile to your project Run bundle install locally (to create
Gemfile.lock file) Push your Gemfile and Gemfile.lock to heroku
That should first install ruby, then run bundle install, then install python, and all deps in the requirements.txt file.
Howeve, in my case, I also wanted to run some commands using ruby libraries, namebly SASS/COMPASS. In order to do that, you have two options I think. First one, is to fork above repository and add running those commands in the build (this way they have all needed privileges rather than you running heroku run ...).
The second options is to add a Rakefile and specify those things in rake assets:precompile task.
So, in my case with Compass the Rakefile looks like:
require 'yaml'
require 'pathname'
require 'rspec/core/rake_task'
include FileUtils
namespace 'assets' do
desc 'Updates the stylesheets generated by Sass/Compass'
task :precompile do
print %x(compass compile --time)
end
end

How can i install external pinax projects?

I try to deal with poor documentation of Pinax.
I found this project
https://github.com/pinax/pinax-multiblog-project
what i want is that install it. I normally install a project called account but here i have to install from git . How can i do that in Pinax
Edit:
It turns out the new way of using projects is to just copy the folder and rename it.
Usage instructions:
So to use the multiblog project you would do
Copy the multiblog inside the cloned repo to a new location and rename it to the name you would like to use for your project. Then install the requirements via pip and follow the rest of the steps for setting up a django project
OSX/Linux:
cd ~/src
git clone https://github.com/pinax/pinax-multiblog-project
cp -r ~/src/pinax-project-admin ~/Sites/new_project
cd ~/Sites/new_project"
pip install -r requirements.txt
python manage.py syncdb
I too have been trying to accomplish the same thing. So far I found this commit
https://github.com/nrb/pinax/blob/476d2398c48cc444eb2338c12090f0cebad46961/docs/starterprojects.txt
Relevant section on begins on line 160 near the end
External Starter Projects
=========================
The Pinax ``setup_project`` command can also use starter projects built by third parties.
These can either be plain directory structures, or they may be a git/hg pip editable.
To install a starter project from an external source, simply pass the file path or git/hg
URL to the ``-b`` option::
pinax-admin setup_project -b git+git://github.com/user/project.git#egg=project my_new_project
However all the pinax projects I have come across don't seem to include an egg to use
eg:
https://github.com/pinax/pinax-multiblog-project
https://github.com/pinax/pinax-project-account
I need to use Django 1.4 for my project but the included account base project in both Pinax 0.9a2 and 0.9b1-dev10 use Django 1.3.
I am guessing the external project integration is something we will have to wait for in the Pinax 1.0 release.

How to link a folder with an existing Heroku app with mercurial

I have an existing Django app on Bitbucket and I'm able to deploy to Heroku whith hg-git. Whenever i want to run some heroku command inside my app folder i get the following errors:
$ heroku ps
! No app specified.
! Run this command from an app folder or specify which app to use with --app <app name>
$ heroku logs
! No app specified.
! Run this command from an app folder or specify which app to use with --app <app name>
etc.
Current workaround is to specify the app name: heroku ps --app <app name> but i'm looking for a way to link my repository name to the remote Heroku app name like how it's done using git.
I'm not in a position to move my app to github for now.
I'd suggest trying Hg-Git's "intree" configuration option. Set that by adding the following to your hgrc:
[git]
intree = True
With that set, the Git repository used internally by Hg-Git will be stored as a ".git" directory within the working copy, rather than nested within the ".hg" directory.
Heroku will then see this repository's config. Add a remote as suggested in the other answer (quoted below), and you should be all set.
git remote add heroku git#heroku.com:<app-name>.git
For now, the best documentation of Hg-Git configuration options that I've found is the README displayed on the project's Bitbucket page: https://bitbucket.org/durin42/hg-git
Considering heroku is looking at the .git/config file to get the app name, just do the following inside your local repository:
git init
git remote add heroku git#heroku.com:<app-name>.git
In order not to mess your repository, you'll also add the following lines to .hgignore:
#Git setup
.git/**
Now, usual heroku commands no more ask for the default app name.

django + virtualenv = atomic upgrade - is it possible?

I have a Django project running within a virtualenv with no site-packages. When it comes to pushing my new changes to the server, I would like to create a new virtualenv directory, install my project and all its dependancies, then do a quick renaming of the two virtualenv directories ONLY if the new code deployed successfully.
All is great on paper, till the point you rename the virtualevn directory. Relocate option on virtualenv is not reliable as per its documentation.
How do you suggest upgrading my project ONLY if the new code is proven to be deployable.
Here are the steps:
# fab update_server to run the following:
cd /srv/myvenv # existing instance
cd ../
virtualenv myenv-1
source myenv-1/bin/activate
git co http://my.com/project
pip install -r project/req.txt
# all worked
mv myenv myenv-2; mv myenv-1 myenv
touch /path/proj.wsgi # have apache to reload us
The above is perfect, but renaming or relocating virtualenv is not reliable.
Upgrading the live site within myvenv takes time and may break the site too.
How would you do it?
Buildout?
I do it with symlinks and completely separate release directories. Ie, a deployment involves cloning the entire project into a new directory, building the virtualenv inside that, then switching the "production" symlink to point at that directory.
My layout is basically
/var/www/myapp/
uploads/
tmp/
releases/
001/myapp/
002/myapp/
003/myapp/
ve/
...etc in each release directory...
myapp # symlink to releases/003/myapp/
So, when I deploy to production, my deployment scripts rsync a completely fresh copy to /var/www/myapp/releases/004/myapp/, build a virtualenv in there, install all the packages into it, then
rm -f /var/www/myapp/myapp
ln -s /var/www/myapp/releases/004/myapp/ /var/www/myapp/myapp
My actual deployment script is a little more complicated as I also make sure to keep the previous release around and marked so if I notice that something is really broken, rolling back is just a matter of switching the symlink to point back at the previous one. (some extra work is also necessary to clean up old, unused releases if you are worried about the disk space).
Every external reference (in apache config files or wsgi files or whatever) point at libraries and binaries in the virtualenv as /var/www/myapp/myapp/ve/. I also shun the use of source ve/bin/activate and instead point at the full path in config files and I edit manage.py to use #!ve/bin/python so I can run commands with ./manage.py whatever and it will always work without me having to remember if I've activated the right virtualenv.