【问题标题】:django-hstore on HerokuHeroku 上的 django-hstore
【发布时间】:2012-11-05 04:14:57
【问题描述】:

我在 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 更友好)

【问题讨论】:

  • 你最后做了什么?我正在考虑使用带有 Django 和 Heroku 的 HStore,并且在进入它之前对这个陷阱保持警惕。

标签: python django heroku psycopg2 hstore


【解决方案1】:

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"

【讨论】:

  • 值得我在 Django 1.5 中使用它的变体,它似乎正在工作。我必须添加一个咒语才能使其与 South 顺利配合。
【解决方案2】:

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

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

作为奖励,与您链接到的 original django-hstore 相比,该仓库的维护时间要晚得多,而后者已多年未触及……可怕。

【讨论】:

  • 确实如此。 django-hstore 似乎不再维护,而 djorm-ext-hstore 处于活动状态。
【解决方案3】:

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

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

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2016-12-08
    • 2011-12-03
    • 2016-12-16
    • 2021-03-04
    • 2012-05-06
    • 1970-01-01
    • 2013-12-03
    • 2020-01-16
    相关资源
    最近更新 更多