I've installed the hstore extension successfully, and everything works when I syncdb
. (I'm using djorm-ext-hstore)
However, nose creates a new temp database to run tests in, and hstore is not installed in it.
I need to run CREATE EXTENSION HSTORE;
on the test db right before nose syncs the db, but I can't find any info on how to do that.
Any ideas?
This is a non-issue: The best way to fix this is to apply the hstore extension on the default database, template1
psql -d template1 -c 'create extension hstore;'
Reference: How to create a new database with the hstore extension already installed?
With Django 1.8:
from django.contrib.postgres.operations import HStoreExtension
class Migration(migrations.Migration):
...
operations = [
HStoreExtension(),
...
]
https://docs.djangoproject.com/en/1.8/ref/contrib/postgres/fields/#hstorefield
EDIT: Just note that there is also a JSONField which handles (un)marshalling of json already and inline search. The HStoreExtension is not necessary for it. Requires Django >=1.11 and Postgres >=9.4.
Also you can run sql command in a migration (Django 1.8):
class Migration(migrations.Migration):
# ...
operations = [
migrations.RunSQL('create extension hstore;'),
# ...
I'm assuming you're using django-nose. In this case you should create your own TestSuiteRunner
:
from django.db import connections, DEFAULT_DB_ALIAS
from django_nose import NoseTestSuiteRunner
class MyTestSuiteRunner(NoseTestSuiteRunner):
def setup_databases(self):
result = super(MyTestSuiteRunner, self).setup_databases()
connection = connections[DEFAULT_DB_ALIAS]
cursor = connection.cursor()
cursor.execute('CREATE EXTENSION HSTORE')
return result
Then in settings.py
you should specify your custom test runner:
TEST_RUNNER = 'path.to.my.module.MyTestSuiteRunner'
Since my last answer, Django deprecated and removed pre_syncdb
signal. I've updated the answer to accommodate more recent versions. The basic mechanics are identical for newer versions as both methods rely on signals and the SQL code that only executes if HSTORE extension does not exist.
Django 1.8+
Since Django introduced DB migrations, pre_syncdb
signals were marked deprecated in 1.7 and completely removed in 1.9. However, they introduced a new signal called pre_migrate
which can be used the same way.
"""
This is an example models.py which contains all model definition.
"""
from django.dispatch import receiver
from django.db import connection, models
from django.db.models.signals import pre_syncdb
import sys
# The sender kwarg is optional but will be called for every pre_syncdb signal
# if omitted. Specifying it ensures this callback to be called once.
@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+ (original answer)
My suggestion is to use pre_syncdb
signal hook.
See my answer on the other question.
"""
This is an example models.py which contains all model definition.
"""
from django.dispatch import receiver
from django.db import connection, models
from django.db.models.signals import pre_syncdb
import sys
# The sender kwarg is optional but will be called for every pre_syncdb signal
# if omitted. Specifying it ensures this callback to be called once.
@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.
The pre_syncdb
signal is fired before the model table is created, making it ideal to ensure the extension is installed when the test database is being set up every time. The IF NOT EXISTS
ensures that PostgreSQL ignores the command if the extension is already installed. You'll get an error if you run CREATE EXTENSION
on an extension that already exists.
This works for the default Django unit test framework and will most likely work for Django nose tests.
More info on signals:
https://docs.djangoproject.com/en/1.6/ref/signals/#management-signals