Heroku上的django-hstore

时间:2012-11-05 04:14:57

标签: python django heroku psycopg2 hstore

我在Heroku(雪松堆栈)上部署了一个Django(v 1.3.3)项目。它使用推荐的dj_database_url来配置settings.DATABASES。一切都很好(到目前为止)。

但是,我想开始使用django-hstore作为部分应用程序。根据文档,您必须将settings.py中的数据库引擎更改为:

'ENGINE': 'django_hstore.postgresql_psycopg2',

结果,在我的settings.py文件中,我执行以下操作:

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

一切都适合我,在当地。我的拥有hstore字段的模型运行良好(值是字典)。

但是,当我部署到Heroku时,数据库引擎被重置/覆盖为:

ENGINE: 'django.db.backends.postgresql_psycopg2'

在试图调试它时,我在设置文件中设置引擎后放了一个打印件。然后,我运行bash:

heroku run bash

然后:

python myapp/manage.py shell

当我运行它时,我的print语句向我显示了所需引擎(django_hstore.postgresql_psycopg2)的正确(所需)数据库设置。但是,如果我这样做:

from django.conf import settings
print settings.DATABASES

我可以看到数据库引擎不再是django_hstore,而是设置回正常(非hstore)值。如果我导入我的一个模型并执行加载对象,则hstore字段中的值是一个字符串,任何访问键的尝试都会抛出并出错:

TypeError: string indices must be integers, not str

请记住,这项工作在当地找到。但是,在部署到heroku之后,任何以字典形式访问值的尝试都会抛出TypeError。

我的问题是:

  • 有谁知道为什么我的引擎被覆盖了?如果是这样,我该如何解决这个问题?

  • 是否有另一种方法可以使用带有Django 1.3.3的hstore字段,可能不需要更改引擎(因此可以更友好地使用Heroku)

3 个答案:

答案 0 :(得分:2)

SQLAlchemy 0.8包含可用于创建custom model以处理Python dict和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"

此模型是可移植的,但如果您想基于hstore键或值运行查询,则必须在原始SQL中编写它们。

我使用SQLite内存数据库来运行测试,只要你对非PostgreSQL后端使用text类型就可以正常工作:

    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"

答案 1 :(得分:1)

https://github.com/niwibe/djorm-ext-hstore

看起来这个软件包最初是django-hstore的一个分支,包含相同的功能,但已经更新,不再需要自定义数据库后端,这似乎可以缓解您的问题。 (请注意,其中一些查询语法已更改)。

作为奖励,回购的维护时间远远超过您链接到的original django-hstore,这在几年内没有被触及......可怕。

答案 2 :(得分:1)

很高兴告诉你django_hstore的新版本1.2.1已经发布了

通过pip升级并检查新的官方django-hstore github存储库:https://github.com/djangonauts/django-hstore