sql >> Databáze >  >> RDS >> Mysql

Django ManyToMany prostřednictvím více databází

Existuje řešení pro Django 1.6+ (včetně 1.11) pro MySQL a sqlite backends, podle možnosti ForeignKey. db_constraint =Nepravda a explicitní Meta.db_table . Pokud je název databáze a název tabulky uvozován pomocí ' ' ' (pro MySQL) nebo ' " ' (pro jiné db), např. db_table = '"db2"."table2"' ). Pak se více neuvozuje a tečka je mimo uvozovku. Platné dotazy sestavuje Django ORM. Lepším podobným řešením je db_table = 'db2"."table2' (to umožňuje nejen připojení, ale je také o jeden problém blíže migraci omezení db)

db2_name = settings.DATABASES['db2']['NAME']

class Table1(models.Model):
    fk = models.ForeignKey('Table2', on_delete=models.DO_NOTHING, db_constraint=False)

class Table2(models.Model):
    name = models.CharField(max_length=10)
    ....
    class Meta:    
        db_table = '`%s`.`table2`' % db2_name  # for MySQL
        # db_table = '"db2"."table2"'          # for all other backends
        managed = False

Sada dotazů:

>>> qs = Table2.objects.all()
>>> str(qs.query)
'SELECT "DB2"."table2"."id" FROM DB2"."table2"'
>>> qs = Table1.objects.filter(fk__name='B')
>>> str(qs.query)
SELECT "app_table1"."id"
    FROM "app_table1"
    INNER JOIN "db2"."app_table2" ON ( "app_table1"."fk_id" = "db2"."app_table2"."id" )
    WHERE "db2"."app_table2"."b" = 'B'

Tato analýza dotazu je podporována všemi backendy db v Django, nicméně další nezbytné kroky musí být projednány individuálně s backendy. Snažím se odpovědět obecněji, protože jsem našel podobná důležitá otázka .

Volba 'db_constraint' je nezbytná pro migrace, protože Django nemůže vytvořit referenční integritní omezení
ADD foreign key table1(fk_id) REFERENCES db2.table2(id) ,
ale lze vytvořit ručně pro MySQL.

Otázkou u konkrétních backendů je, zda lze k výchozí databázi za běhu připojit další databázi a zda je podporován cizí klíč mezi databázemi. Tyto modely jsou také zapisovatelné. Nepřímo připojená databáze by měla být použita jako starší databáze s managed=False (protože pouze jedna tabulka django_migrations pro sledování migrací se vytváří pouze v přímo připojené databázi. Tato tabulka by měla popisovat pouze tabulky ve stejné databázi.) Indexy pro cizí klíče však lze na spravované straně vytvářet automaticky, pokud databázový systém takové indexy podporuje.

Sqlite3 :Musí být připojen k jiné výchozí databázi sqlite3 za běhu (odpověď SQLite – Jak spojujete tabulky z různých databází ), v nejlepším případě signálem connection_created :

from django.db.backends.signals import connection_created

def signal_handler(sender, connection, **kwargs):
    if connection.alias == 'default' and connection.vendor == 'sqlite':
        cur = connection.cursor()
        cur.execute("attach '%s' as db2" % db2_name)
        # cur.execute("PRAGMA foreign_keys = ON")  # optional

connection_created.connect(signal_handler)

Pak to samozřejmě nepotřebuje databázový router a normální django...ForeignKey lze použít s db_constraint=False. Výhodou je, že "db_table" není nutné, pokud jsou názvy tabulek mezi databázemi jedinečné.

V MySQL cizí klíče mezi různými databázemi jsou snadné. Všechny příkazy jako SELECT, INSERT, DELETE podporují libovolné názvy databází bez předchozího připojení.

Tato otázka se týkala starších databází. Mám však několik zajímavých výsledků také s migrací.



  1. Co je testování databáze a jak jej provádět?

  2. Seznam území podporovaných databází Oracle

  3. Co znamená ON [PRIMARY]?

  4. Zadanému názvu a typu argumentu neodpovídá žádný operátor. Možná budete muset přidat explicitní přetypování. -- Netbeans, Postgresql 8.4 a Glassfish