3

我在 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

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

from django.conf import settings
print settings.DATABASES

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

TypeError: string indices must be integers, not str

请记住,此作品可在本地找到。但是,在部署到 heroku 之后,任何将值作为字典访问的尝试都会抛出上面的 TypeError。

我的问题是:

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

或者

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

3 回答 3

2

SQLAlchemy 0.8包含实用方法,可用于创建自定义模型以处理 Pythondict和 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 内存数据库来运行测试,只要您将text类型用于非 PostgreSQL 后端,它就可以正常工作:

    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"
于 2013-02-24T03:20:01.530 回答
1

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

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

于 2014-02-28T14:53:38.583 回答
1

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

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

作为奖励,与您链接到的原始 django-hstore相比,repo 的维护时间要晚得多,后者多年来没有被触及……可怕。

于 2013-03-15T04:52:21.923 回答