sql >> Database teknologi >  >> RDS >> Mysql

Django ManyToMany igennem med flere databaser

Der findes en løsning til Django 1.6+ (inklusive 1.11) til MySQL og sqlite backends efter mulighed ForeignKey. db_constraint =Falsk og eksplicit Meta.db_table . Hvis databasenavnet og tabelnavnet er anført af ' ` ' (for MySQL) eller af ' " ' (for andre db), f.eks. db_table = '"db2"."table2"' ). Så er det ikke citeret mere, og prikken er ude af citeret. Gyldige forespørgsler kompileres af Django ORM. En bedre lignende løsning er db_table = 'db2"."table2' (der tillader ikke kun joinforbindelser, men det er også af ét problem tættere på at krydse db-begrænsningsmigrering)

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

Forespørgselssæt:

>>> 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'

Denne forespørgselsparsing understøttes af alle db-backends i Django skal andre nødvendige trin dog diskuteres individuelt af backends. Jeg forsøger at svare mere generelt, fordi jeg fandt en lignende vigtigt spørgsmål .

Indstillingen 'db_constraint' er nødvendig for migreringer, fordi Django ikke kan oprette referenceintegritetsbegrænsningen
ADD foreign key table1(fk_id) REFERENCES db2.table2(id) ,
men den kan oprettes manuelt til MySQL.

Et spørgsmål for bestemte backends er, om en anden database kan forbindes til standarden under kørsel, og om en fremmednøgle på tværs af databaser er understøttet. Disse modeller er også skrivbare. Den indirekte forbundne database skal bruges som en ældre database med managed=False (fordi kun én tabel django_migrations til migreringer oprettes sporing kun i den direkte tilsluttede database. Denne tabel bør kun beskrive tabeller i samme database.) Indekser til fremmednøgler kan dog oprettes automatisk på den administrerede side, hvis databasesystemet understøtter sådanne indekser.

Sqlite3 :Den skal vedhæftes en anden standard sqlite3-database ved kørsel (svar SQLite - Hvordan forbinder du tabeller fra forskellige databaser ), i bedste fald ved signalet 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)

Så behøver den selvfølgelig ikke en databaserouter og en normal django...ForeignKey kan bruges med db_constraint=False. En fordel er, at "db_table" ikke er nødvendig, hvis tabelnavnene er unikke mellem databaser.

I MySQL fremmednøgler mellem forskellige databaser er nemme. Alle kommandoer som SELECT, INSERT, DELETE understøtter alle databasenavne uden at vedhæfte dem tidligere.

Dette spørgsmål handlede om ældre databaser. Jeg har dog nogle interessante resultater også med migreringer.



  1. Sådan kombinerer du resultaterne af to forespørgsler i SQL

  2. PostgreSQL listevisninger

  3. Sådan kombinerer du GROUP BY, ORDER BY og HAVING

  4. 4 måder at liste alle tabeller i en MySQL-database