23

この素晴らしいチュートリアルを使用して、django-hstore を使用しようとしました。South が管理する既存のアプリに 2 つのクラスを追加しました。

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

さて、チュートリアルは不完全なようでした。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 に答える
4

pre_syncdb私の最後の回答以来、Djangoは非推奨になり、シグナルを削除しました。より最近のバージョンに対応するように回答を更新しました。どちらの方法も信号と、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 拡張機能が確実にインストールされるようにする 1 つの方法は、 Django 1.6で導入されたファイル内のシグナル./manage.py syncdbを利用することです。pre_syncdbmodels.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 に答える