2015-08-05 5 views
3

Конкретный случай использования:Сделать миграции Условное в Django

A Django module хочет создать расширение во время миграции. Если пользователь DB, который используется для запуска миграции, не является суперпользователем, этот не работает.

Существует несколько способов решения этой проблемы: один из способов (гипотетически) проверить файл миграции, независимо от того, установлено ли расширение и запускать только этот код SQL, если он не установлен.

После некоторых исследований, похоже, что Django RunSQL может возвращать результаты и впоследствии исключать операции в зависимости от результата предыдущей операции. Будут ли другие способы достижения этого? (Например, подклассы RunSQL?)

Любое решение, основанное на Django миграции, настройки Django или Postgres внутренний (один SQL заявление, что достигает запустить CREATE EXTENSION только, если определенное условие истинно) будет в порядке.

(Обратите внимание, что я упомянул Джанго-pgcrypto-поля только для иллюстрации мне интересно знать, существует ли такое решение в целом.).

EDIT в ответ на комментарий Anentropic в: решение должно работать при запуске команд test или jenkins. Это означает, что вручную вызывается --fake-initial или аналогично, чтобы избежать выполнения этой миграции, это не вариант. Если вы можете объяснить, как сделать test подделкой определенных миграций, это наиболее приветствуется.

Мое текущее решение добавить следующее settings:

MIGRATION_MODULES = { 
    'pgcrypto_fields': 'do-not-run-migrations' 
} 

Но это приведет к отключению всех миграций в вопросе и не только обижая один. В этом случае это может сработать, но я вижу это как удачную и уродливую работу.

+0

Модуль нуждается в расширении, чтобы работать, поэтому вам нужно найти способ создания расширения. Я бы предложил создать расширение в качестве администратора, а затем [fake] (https://docs.djangoproject.com/en/1.8/ref/django-admin/# django-admin-option --- подделка). Соответствующая миграция – Anentropic

+0

@ Энтропник Спасибо за предложение. К сожалению, это не будет работать с 'manage.py test', imho. Я отредактировал свой вопрос в ответ на ваш комментарий. – Risadinha

+0

Если это для запуска тестов, я бы предложил использовать разные настройки db для тестов, вашему пользователю django db можно было бы получить доступ администратора к тесту db – Anentropic

ответ

0

Фактически, Django's HStoreExtension работает только при необходимости. Но, конечно, для него все еще требуется доступ к суперпользователю. Для pgcrypto может быть создан класс, аналогичный HStoreExtension.

Установка для выполнения им в тестах по-прежнему требует доступ суперпользователя, поэтому настройки должны выглядеть следующим образом:

INSTALLED_APPS = (
    ... 
    'django.contrib.postgres', 
    ... 
) 

if sys.argv[1] in ['test', 'jenkins']: 
    # Install extension hstore (requires superuser) 
    INSTALLED_APPS = ('test_init',) + INSTALLED_APPS 

    # a superuser 
    DATABASES["default"]["USER"] = 'xxx' 
    DATABASES["default"]["PASSWORD"] = 'xxx' 

и «test_init» Джанго приложение содержит только необходимый __init.py__ и модуль Миграции с следующий файл 0001_initial.py:

# -*- coding: utf-8 -*- 
from __future__ import unicode_literals 
from django.contrib.postgres.operations import HStoreExtension 

from django.db import migrations 


class Migration(migrations.Migration): 

    run_before = [ 
     ('some_app_that_requires_hstore', '0001_initial'), 
    ] 

    operations = [ 
     HStoreExtension(), 
    ] 

Это на самом деле не требуется, чтобы проверить режим тестирования (через sys.argv), чтобы сделать миграцию только тогда. Как упоминалось выше, HStoreExtension не знает об ошибках. Так что даже если вы запустите migrate на производство без суперпользователя, это не подведет, независимо от того, установлен ли hstore. См. Его исходный код.

См. Также Django's documentation of HStoreField.

Смежные вопросы