web-dev-qa-db-fra.com

Comment exécuter du SQL brut dans une migration Django

Je connais l'objet curseur dans Django. Existe-t-il un autre moyen préféré d'exécuter du SQL brut dans les migrations? Je veux introduire le partitionnement postgresql pour l'une de mes tables de modèles. La logique de partition est un tas de fonctions et de déclencheurs qui doivent être ajoutés à la base de données lors de la configuration que j'aimerais automatiser.

22
David Schumann

Une manière:

La meilleure façon de le faire est d'utiliser RunSQL:

Migrations contient la classe RunSQL. Pour faire ça:

  1. ./manage.py makemigrations --empty myApp
  2. éditez le fichier de migrations créé pour inclure:

operations = [ migrations.RunSQL('RAW SQL CODE') ]

Comme Nathaniel Knight l'a mentionné, RunSQL accepte également un paramètre reverse_sql Pour inverser la migration. Voir la documentation pour plus de détails

Autrement

La façon dont j'ai résolu mon problème au départ était d'utiliser le signal post_migrate Pour appeler un curseur pour exécuter mon SQL brut.

Ce que je devais ajouter à mon application était le suivant:

dans le __init__.py de myApp ajoutez:

default_app_config = 'myApp.apps.MyAppConfig'

Créez un fichier apps.py:

from Django.apps import AppConfig
from Django.db.models.signals import post_migrate
from myApp.db_partition_triggers import create_partition_triggers


class MyAppConfig(AppConfig):
    name = 'myApp'
    verbose_name = "My App"

    def ready(self):
        post_migrate.connect(create_partition_triggers, sender=self)

Nouveau fichier db_partition_triggers.py:

from Django.db import connection


def create_partition_triggers(**kwargs):
    print '  (re)creating partition triggers for myApp...'
    trigger_sql = "CREATE OR REPLACE FUNCTION...; IF NOT EXISTS(...) CREATE TRIGGER..."
    cursor = connection.cursor()
    cursor.execute(trigger_sql)
    print '  Done creating partition triggers.'

Désormais, tous les manage.py syncdb Ou manage.py migrate Cette fonction est appelée. Assurez-vous donc qu'il utilise CREATE OR REPLACE Et IF NOT EXISTS. Il peut donc gérer les fonctions existantes.

39
David Schumann

Je recommanderais Django-migrate-sql-deux https://pypi.org/project/Django-migrate-sql-deux/

De cette façon, vous pouvez gérer des objets de base de données comme des vues, des fonctions, des déclencheurs de manière déclarative comme des modèles dans Django. Ensuite, vous devez générer des modifications dans Django migrations via makemigrations. Et les appliquer via migrate. Ainsi, le flux de développement et de déploiement est assez identique.

Ce serait génial si Django aurait ce système pour les "modèles" SQL bruts et gérerait automatiquement les migrations et les dépendances dans les commandes makemigrations et migrate comme Django-migrate-sql-deux.

0
Petr Přikryl