type postgres fields contrib arrayagg python django psycopg2 hstore

python - postgres - ¿Cómo configurar django-hstore con una aplicación existente administrada por south?



django y postgresql (3)

Intenté usar django-hstore usando este bonito tutorial . Agregué dos clases a una aplicación existente administrada por 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()

realizó un schemamigration --auto , lanzó la migración y obtuvo un django.db.utils.DatabaseError: type "hstore" does not exist .

De acuerdo, el tuto parecía estar incompleto, la documentation django-hstore me dijo que usara la base de datos personalizada, agregué lo siguiente a mi archivo de configuración:

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

Luego obtuve un KeyError: ''default'' en south/db/__init__.py", line 78 En este punto, los intertubes + algunos ensayos / errores me SOUTH_DATABASE_ADAPTERS variable de configuración SOUTH_DATABASE_ADAPTERS y SOUTH_DATABASE_ADAPTERS lo siguiente a la configuración:

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

Nuevo error:

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

Ahora esto es extraño porque instalé la extensión 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)

Cómo se supone que esto funcione ? Estoy usando Django 1.4, Postgresql 9.1.


Desde mi última respuesta, Django desaprobó y eliminó la señal pre_syncdb . He actualizado la respuesta para acomodar las versiones más recientes. Los mecanismos básicos son idénticos para las versiones más recientes, ya que ambos métodos se basan en las señales y en el código SQL que solo se ejecuta si no existe la extensión HSTORE.

Django 1.8+

Desde que Django introdujo las migraciones de DB, pre_syncdb señales pre_syncdb se marcaron en desuso en 1.7 y se eliminaron completamente en 1.9 . Sin embargo, introdujeron una nueva señal llamada pre_migrate que puede usarse de la misma manera.

Ejemplo:

""" 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+ (respuesta original)

Una forma de asegurarse de que la extensión HSTORE se instale durante ./manage.py syncdb es utilizar señales pre_syncdb en su archivo models.py que se introdujo con Django 1.6 .

Ejemplo:

""" 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.

Me parece que esto es útil si no desea ejecutarlo para cada nueva instancia de base de datos. Este método también funciona para las pruebas unitarias de Django durante la configuración de la base de datos de prueba.

Más información sobre los enlaces de señal en Django: https://docs.djangoproject.com/en/1.6/ref/signals/#management-signals



Finalmente descubrí que la extensión hstore no estaba instalada para la base de datos específica que estaba usando:

$ 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)

Pensé que una base de datos creada después de la instalación de hstore incluiría la extensión. No parece ser el caso, ¿ estoy malinterpretando cómo funcionan las extensiones? ¿Son específicos de la base de datos?