├── .gitignore ├── .travis.yml ├── MANIFEST.in ├── README.md ├── UNLICENSE ├── assets └── postgresify.jpg ├── postgresify.py ├── requirements.txt ├── setup.py └── tests.py /.gitignore: -------------------------------------------------------------------------------- 1 | dist 2 | *.egg-info 3 | build 4 | -------------------------------------------------------------------------------- /.travis.yml: -------------------------------------------------------------------------------- 1 | language: python 2 | python: 3 | - "2.7" 4 | - "3.2" 5 | - "3.3" 6 | - "3.4" 7 | install: 8 | - python setup.py develop 9 | - pip install -r requirements.txt 10 | script: 11 | - nosetests 12 | -------------------------------------------------------------------------------- /MANIFEST.in: -------------------------------------------------------------------------------- 1 | include README.md requirements.txt tests.py UNLICENSE 2 | recursive-include assets *.jpg 3 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # django-heroku-postgresify 2 | 3 | Automatic Django database configuration on Heroku. 4 | 5 | 6 | ![What if configuring PostgreSQL is really easy?](https://github.com/rdegges/django-heroku-postgresify/raw/master/assets/postgresify.jpg) 7 | 8 | 9 | ## Install 10 | 11 | To install ``django-heroku-postgresify``, simply run 12 | ``pip install django-heroku-postgresify`` and you'll get the latest version 13 | installed automatically. 14 | 15 | 16 | ## Usage 17 | 18 | Modify your Django ``settings.py`` file, and set: 19 | 20 | ``` python 21 | from postgresify import postgresify 22 | 23 | DATABASES = postgresify() 24 | ``` 25 | 26 | That's it. 27 | 28 | Depending on the Heroku PostgreSQL databases you've got installed, your 29 | ``DATABASES`` configuration will automatically be setup to use them. 30 | 31 | For example, let's assume you've got the following environment variables set on 32 | Heroku (you can view the list of all environment variables by running ``heroku 33 | config``): 34 | 35 | - ``HEROKU_POSTGRESQL_BLUE_URL`` 36 | - ``HEROKU_POSTGRESQL_RED_URL`` 37 | - ``HEROKU_SHARED_POSTGRESQL_RED_URL`` 38 | - ``SHARED_DATABASE_URL`` 39 | - ``DATABASE_URL`` 40 | 41 | Your ``DATABASES`` setting would be: 42 | 43 | ``` python 44 | DATABASES = { 45 | 'default': { 46 | # DATABASE_URL configs here 47 | }, 48 | 'SHARED': { 49 | # SHARED_DATABASE_URL configs here 50 | }, 51 | 'BLUE': { 52 | # HEROKU_POSTGRESQL_BLUE_URL configs here 53 | }, 54 | 'RED': { 55 | # HEROKU_POSTGRESQL_RED_URL configs here 56 | }, 57 | 'SHARED_RED': { 58 | # HEROKU_SHARED_POSTGRESQL_RED_URL configs here 59 | }, 60 | } 61 | ``` 62 | 63 | 64 | ## References 65 | 66 | If you're confused, you should probably read: 67 | 68 | - [Heroku's Getting Started Guide](http://devcenter.heroku.com/articles/django) 69 | - [Deploy Django's PostgreSQL Section](http://www.deploydjango.com/postgresql/index.html) 70 | 71 | 72 | ## Tests 73 | 74 | [![Build Status](https://secure.travis-ci.org/rdegges/django-heroku-postgresify.png?branch=master)](http://travis-ci.org/rdegges/django-heroku-postgresify) 75 | 76 | Want to run the tests? No problem: 77 | 78 | ``` bash 79 | $ git clone git://github.com/rdegges/django-heroku-postgresify.git 80 | $ cd django-heroku-postgresify 81 | $ python setup.py develop 82 | ... 83 | $ pip install -r requirements.txt # Install test dependencies. 84 | $ nosetests 85 | ............. 86 | ---------------------------------------------------------------------- 87 | Ran 13 tests in 0.166s 88 | 89 | OK 90 | ``` 91 | -------------------------------------------------------------------------------- /UNLICENSE: -------------------------------------------------------------------------------- 1 | This is free and unencumbered software released into the public domain. 2 | 3 | Anyone is free to copy, modify, publish, use, compile, sell, or 4 | distribute this software, either in source code form or as a compiled 5 | binary, for any purpose, commercial or non-commercial, and by any 6 | means. 7 | 8 | In jurisdictions that recognize copyright laws, the author or authors 9 | of this software dedicate any and all copyright interest in the 10 | software to the public domain. We make this dedication for the benefit 11 | of the public at large and to the detriment of our heirs and 12 | successors. We intend this dedication to be an overt act of 13 | relinquishment in perpetuity of all present and future rights to this 14 | software under copyright law. 15 | 16 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 17 | EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 18 | MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. 19 | IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR 20 | OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, 21 | ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR 22 | OTHER DEALINGS IN THE SOFTWARE. 23 | 24 | For more information, please refer to 25 | -------------------------------------------------------------------------------- /assets/postgresify.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/rdegges/django-heroku-postgresify/16d86bc401b9030f1f3f6b9f6d1b5175671687fa/assets/postgresify.jpg -------------------------------------------------------------------------------- /postgresify.py: -------------------------------------------------------------------------------- 1 | from os import environ 2 | 3 | from dj_database_url import config 4 | 5 | 6 | # Some constant globals that Heroku uses. 7 | DEFAULT_URL = 'DATABASE_URL' 8 | SHARED_URL = 'SHARED_DATABASE_URL' 9 | 10 | 11 | def postgresify(): 12 | """Return a fully configured Django ``DATABASES`` setting. We do this by 13 | analyzing all environment variables on Heroku, scanning for postgres DBs, 14 | and then making shit happen, duh. 15 | 16 | Returns a fully configured databases dict. 17 | """ 18 | databases = {} 19 | 20 | # If the special ``DATABASE_URL`` variable is set, use this as the 21 | # 'default' database for Django. 22 | if environ.get(DEFAULT_URL, ''): 23 | databases['default'] = config() 24 | 25 | # If there is a legacy ``SHARED_DATABASE_URL`` variable set, assign this 26 | if environ.get(SHARED_URL, '') and databases.get('default', '') != config(env=SHARED_URL): 27 | databases['SHARED_DATABASE'] = config(env=SHARED_URL) 28 | 29 | # Analyze all environment variables looking for databases: 30 | for key in environ.keys(): 31 | 32 | # If this is a Heroku PostgreSQL database: 33 | if key.startswith('HEROKU_') \ 34 | and 'POSTGRESQL' in key \ 35 | and key.endswith('_URL') \ 36 | and databases.get('default', '') != config(env=key): 37 | 38 | # Generate a human-friendly database name: 39 | db_name = key.split('_') 40 | db_name.remove('HEROKU') 41 | db_name.remove('POSTGRESQL') 42 | db_name.remove('URL') 43 | db_name = '_'.join(db_name) 44 | 45 | databases[db_name] = config(env=key) 46 | 47 | return databases 48 | -------------------------------------------------------------------------------- /requirements.txt: -------------------------------------------------------------------------------- 1 | nose==1.1.2 2 | -------------------------------------------------------------------------------- /setup.py: -------------------------------------------------------------------------------- 1 | from os.path import abspath, dirname, join, normpath 2 | 3 | from setuptools import setup 4 | 5 | 6 | setup( 7 | 8 | # Basic package information: 9 | name = 'django-heroku-postgresify', 10 | version = '0.4.1', 11 | py_modules = ('postgresify',), 12 | 13 | # Packaging options: 14 | zip_safe = False, 15 | include_package_data = True, 16 | 17 | # Package dependencies: 18 | install_requires = ['Django>=1.2', 'dj-database-url>=0.3.0'], 19 | 20 | # Metadata for PyPI: 21 | author = 'Randall Degges', 22 | author_email = 'rdegges@gmail.com', 23 | license = 'UNLICENSE', 24 | url = 'https://github.com/rdegges/django-heroku-postgresify', 25 | keywords = 'django heroku cloud postgresql postgres db database awesome epic', 26 | description = 'Automatic Django database configuration on Heroku.', 27 | long_description = open(normpath(join(dirname(abspath(__file__)), 'README.md'))).read(), 28 | long_description_content_type='text/markdown' 29 | 30 | ) 31 | -------------------------------------------------------------------------------- /tests.py: -------------------------------------------------------------------------------- 1 | from os import environ 2 | from unittest import TestCase 3 | 4 | from postgresify import postgresify 5 | 6 | 7 | class Postgresify(TestCase): 8 | 9 | def test_returns_empty_dict_if_no_dbs_are_available(self): 10 | self.assertEqual(postgresify(), {}) 11 | 12 | def test_detects_database_url(self): 13 | environ['DATABASE_URL'] = 'postgres://abc:def@ec2-23-23-217-149.compute-1.amazonaws.com/xxx' 14 | self.assertTrue(postgresify()['default']) 15 | del environ['DATABASE_URL'] 16 | 17 | def test_detects_shared_database(self): 18 | environ['SHARED_DATABASE_URL'] = 'postgres://abc:def@ec2-23-23-217-149.compute-1.amazonaws.com/xxx' 19 | self.assertTrue(postgresify()['SHARED_DATABASE']) 20 | del environ['SHARED_DATABASE_URL'] 21 | 22 | def test_detects_heroku_postgres_shared_database(self): 23 | environ['HEROKU_SHARED_POSTGRESQL_RED_URL'] = 'postgres://abc:def@ec2-23-23-217-149.compute-1.amazonaws.com/xxx' 24 | self.assertTrue(postgresify()['SHARED_RED']) 25 | del environ['HEROKU_SHARED_POSTGRESQL_RED_URL'] 26 | 27 | def test_detects_heroku_databases(self): 28 | environ['HEROKU_POSTGRESQL_TEAL_URL'] = 'postgres://abc:def@ec2-23-23-217-149.compute-1.amazonaws.com/xxx' 29 | self.assertTrue(postgresify()['TEAL']) 30 | del environ['HEROKU_POSTGRESQL_TEAL_URL'] 31 | 32 | def test_doesnt_include_a_database_twice_if_it_is_set_as_default(self): 33 | environ['DATABASE_URL'] = 'postgres://abc:def@ec2-23-23-217-149.compute-1.amazonaws.com/xxx' 34 | environ['HEROKU_POSTGRESQL_AQUA_URL'] = 'postgres://abc:def@ec2-23-23-217-149.compute-1.amazonaws.com/xxx' 35 | self.assertFalse('AQUA' in postgresify()) 36 | del environ['DATABASE_URL'] 37 | del environ['HEROKU_POSTGRESQL_AQUA_URL'] 38 | 39 | --------------------------------------------------------------------------------