23

我尝试使用这个不错的教程来使用 django-hstore 。我在 South 管理的现有应用程序中添加了两个类:

class Attribute(models.Model):
    name  = models.CharField(max_length=200, verbose_name=_("name"))
    description = models.CharField(max_length=1000, verbose_name=_("description"))

class Measure(models.Model):
    attribute = models.ForeignKey(Attribute)
    data = hstore.DictionaryField(db_index=True)
    objects = hstore.HStoreManager()

做了一个schemamigration --auto,启动了迁移,得到了一个django.db.utils.DatabaseError: type "hstore" does not exist.

好的,tuto 似乎不完整,django-hstore文档告诉我使用自定义数据库后端,我在我的设置文件中添加了以下内容:

DATABASES['default']['ENGINE'] = 'django_hstore.postgresql_psycopg2'

然后我KeyError: 'default'进去了south/db/__init__.py", line 78。此时,intertubes + 一些试验/错误将我指向SOUTH_DATABASE_ADAPTERS设置变量,我将以下内容添加到设置中:

SOUTH_DATABASE_ADAPTERS = {'default': 'south.db.postgresql_psycopg2'}

新错误:

File ".../psycopg2/extras.py", line 769, in register_hstore
"hstore type not found in the database. "
psycopg2.ProgrammingError: hstore type not found in the database. please install it from your 'contrib/hstore.sql' file

现在这很奇怪,因为我安装了 hstore 扩展:

$ sudo -u postgres psql
create extension hstore;
postgres=# CREATE EXTENSION hstore;
ERROR:  extension "hstore" already exists
postgres=# \dx
                           List of installed extensions
  Name   | Version |   Schema   |                   Description                    
---------+---------+------------+--------------------------------------------------
 hstore  | 1.0     | public     | data type for storing sets of (key, value) pairs
 plpgsql | 1.0     | pg_catalog | PL/pgSQL procedural language
(2 rows)
postgres=# SELECT 'hstore'::regtype::oid;
  oid  
-------
 57704
(1 row)

这应该如何工作?我正在使用 Django 1.4、Postgresql 9.1。

4

3 回答 3

23

我最终发现没有为我使用的特定数据库安装 hstore 扩展:

$ psql -d mydb
psql (9.1.4)
Type "help" for help.

mydb=# SELECT t.oid, typarray FROM pg_type t JOIN pg_namespace ns ON typnamespace = ns.oid WHERE typname = 'hstore';
 oid | typarray 
-----+----------
(0 rows)

mydb=# \dx
                 List of installed extensions
  Name   | Version |   Schema   |         Description          
---------+---------+------------+------------------------------
 plpgsql | 1.0     | pg_catalog | PL/pgSQL procedural language
(1 row)

mydb=# create extension hstore;
WARNING:  => is deprecated as an operator name
DETAIL:  This name may be disallowed altogether in future versions of PostgreSQL.
CREATE EXTENSION
mydb=# \dx
                           List of installed extensions
  Name   | Version |   Schema   |                   Description                    
---------+---------+------------+--------------------------------------------------
 hstore  | 1.0     | public     | data type for storing sets of (key, value) pairs
 plpgsql | 1.0     | pg_catalog | PL/pgSQL procedural language
(2 rows)

mydb=# SELECT t.oid, typarray FROM pg_type t JOIN pg_namespace ns ON typnamespace = ns.oid WHERE typname = 'hstore';
  oid  | typarray 
-------+----------
 58800 |    58805
(1 row)

我认为在 hstore 安装后创建的数据库将包含扩展。似乎并非如此,我是否误解了扩展的工作原理?它们是特定于数据库的吗?

于 2012-07-20T15:05:31.760 回答
5

Django 现在包含一个迁移操作来hstore在 PostgreSQL 中创建扩展

from django.contrib.postgres.operations import HStoreExtension

class Migration(migrations.Migration):
    ...

    operations = [
        HStoreExtension(),
        ...
    ]
于 2018-09-14T11:08:20.877 回答
4

自从我上次回答以来,Django 弃用并删除了pre_syncdb信号。我已经更新了答案以适应更新的版本。新版本的基本机制是相同的,因为这两种方法都依赖于信号和仅在 HSTORE 扩展不存在时执行的 SQL 代码。

姜戈 1.8+

由于 Django 引入了 DB 迁移,pre_syncdb信号在 1.7 中被标记为弃用,在 1.9 中被完全删除。然而,他们引入了一个新的信号,称为pre_migrate它可以以相同的方式使用。

例子:

"""
This is an example models.py which contains all model definition.
"""
from django.db import connection, models
from django.db.models.signals import pre_migrate
from django.dispatch import receiver
import sys

# sender is optional but will be called for every pre_migrate signal if removed
@receiver(pre_migrate, sender=sys.modules[__name__])
def setup_postgres_hstore(sender, **kwargs):
    """
    Always create PostgreSQL HSTORE extension if it doesn't already exist
    on the database before syncing the database.
    Requires PostgreSQL 9.1 or newer.
    """
    cursor = connection.cursor()
    cursor.execute("CREATE EXTENSION IF NOT EXISTS hstore")

# ...rest of your model definition goes here
class Foo(models.Model):
    # ...field definitions, etc.

Django 1.6+(原始答案)

确保在此期间安装 HSTORE 扩展的一种方法./manage.py syncdb是利用Django 1.6引入的文件中pre_syncdb的信号。models.py

例子:

"""
This is an example models.py which contains all model definition.
"""
from django.db import connection, models
from django.db.models.signals import pre_syncdb
from django.dispatch import receiver
import sys

# sender is optional but will be called for every pre_syncdb signal if removed
@receiver(pre_syncdb, sender=sys.modules[__name__])
def setup_postgres_hstore(sender, **kwargs):
    """
    Always create PostgreSQL HSTORE extension if it doesn't already exist
    on the database before syncing the database.
    Requires PostgreSQL 9.1 or newer.
    """
    cursor = connection.cursor()
    cursor.execute("CREATE EXTENSION IF NOT EXISTS hstore")

# ...rest of your model definition goes here
class Foo(models.Model):
    # ...field definitions, etc.

如果您不想为每个新的数据库实例运行它,我发现这很有用。此方法也适用于测试数据库设置期间的 Django 单元测试。

有关 Django 中信号挂钩的更多信息: https ://docs.djangoproject.com/en/1.6/ref/signals/#management-signals

于 2014-05-13T08:00:07.580 回答