django-hstore on Heroku
Question: I've got a Django (v 1.3.3) project deployed on Heroku (cedar stack). It uses
the recommended dj_database_url for configuring settings.DATABASES. Everything
works great (to this point).

However, I want to start using [django-
hstore](https://github.com/jordanm/django-hstore) for part of the application.
According to the docs, you have to change the database engine in settings.py
to:

    
    
    'ENGINE': 'django_hstore.postgresql_psycopg2',
    

As a result, in my settings.py file, I do the following:

    
    
    DATABASES = {'default': dj_database_url.config()}
    DATABASES['default']['ENGINE'] = 'django_hstore.postgresql_psycopg2'
    

Everything works fine for me, locally. And my models that have hstore fields
work great (values are dictionaries).

However, when I deploy to Heroku, the database engine gets reset/overridden
to:

    
    
    ENGINE: 'django.db.backends.postgresql_psycopg2'
    

In an attempt at debugging it, I have put a print after setting the engine in
my settings file. Then, I run bash:

    
    
    heroku run bash
    

and then:

    
    
    python myapp/manage.py shell
    

when I run this, my print statement shows me the correct (desired) database
settings with the desired engine (django_hstore.postgresql_psycopg2). However,
if I then do:

    
    
    from django.conf import settings
    print settings.DATABASES
    

I can see the database engine is no longer django_hstore, but set back to the
normal (non-hstore) value. And if I import one of my models and do a get to
load an object, the value in the hstore field is a string, and any attempt to
access a key will throw and error:

    
    
    TypeError: string indices must be integers, not str
    

Please keep in mind that this works find locally. But, after deploying to
heroku, any attempt at accessing values as dictionaries throws the TypeError
above.

My questions are:

  * Does anyone know why my engine is getting overridden? And if so, how do I fix this?

or

  * Is there another way to use the hstore field with Django 1.3.3 that might not require having to change the engine (and therefore be a bit more Heroku friendly)


Answer: [SQLAlchemy 0.8](http://www.sqlalchemy.org/) includes utility methods that can
be used to create a [custom model](http://justcramer.com/2008/08/08/custom-
fields-in-django/) for handling the conversion between Python `dict` and
Postgres `hstore`.

    
    
    from django.db import models
    from sqlalchemy.dialects.postgresql.hstore import _parse_hstore, _serialize_hstore
    
    class HStoreField (models.TextField):
        __metaclass__ = models.SubfieldBase
    
        def __init__(self, *args, **kwargs):
            super(HStoreField, self).__init__(*args, **kwargs)
    
        def to_python(self, value):
            if value is None:
                return None
            if isinstance(value, dict):
                return value
            return _parse_hstore(value)
    
        def get_db_prep_save(self, value, connection):
            if value is None:
                return None
            if isinstance(value, str):
                return value
            return _serialize_hstore(value)
    
        def db_type (self, connection):
             return "hstore"
    

This model is portable, but if you want to run queries based on hstore keys or
values you'll have to write them in raw SQL.

I use an SQLite in-memory database for running tests, which works fine as long
as you use the `text` type for non-PostgreSQL backends:

    
    
        def db_type (self, connection):
            from django.db import connection
            if connection.settings_dict['ENGINE'] == \
                'django.db.backends.postgresql_psycopg2':
                return "hstore"
            else:
                return "text"
    

