Mysql
 sql >> Baza danych >  >> RDS >> Mysql

Django ManyToMany z wieloma bazami danych

Istnieje rozwiązanie dla Django 1.6+ (w tym 1.11) dla MySQL i sqlite backendy, według opcji ForeignKey. db_ograniczenie =Fałsz i jawny Meta.db_table . Jeśli nazwa bazy danych i nazwa tabeli są zacytowane przez ' ` ' (dla MySQL) lub przez ' " ' (dla innej bazy danych), np. db_table = '"db2"."table2"' ). Wtedy nie jest już cytowany, a kropka nie jest cytowana. Poprawne zapytania są kompilowane przez Django ORM. Lepszym podobnym rozwiązaniem jest db_table = 'db2"."table2' (co pozwala nie tylko na połączenia, ale jest również o jeden problem bliższe migracji ograniczeń między bazami danych)

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

Zestaw zapytań:

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

Przetwarzanie zapytania jest obsługiwane przez wszystkie backendy bazy danych w Django, jednak inne niezbędne kroki muszą być omówione indywidualnie przez backendy. Próbuję odpowiedzieć bardziej ogólnie, ponieważ znalazłem podobne ważne pytanie .

Opcja 'db_constraint' jest konieczna w przypadku migracji, ponieważ Django nie może utworzyć ograniczenia integralności referencji
ADD foreign key table1(fk_id) REFERENCES db2.table2(id) ,
ale można utworzyć ręcznie dla MySQL.

Pytanie dla konkretnych backendów brzmi, czy inna baza danych może być podłączona do domyślnej w czasie wykonywania i czy obsługiwany jest klucz obcy między bazami danych. Modele te można również pisać. Pośrednio podłączona baza danych powinna być używana jako starsza baza danych z managed=False (ponieważ tylko jedna tabela django_migrations śledzenie migracji jest tworzone tylko w bezpośrednio połączonej bazie danych. Ta tabela powinna opisywać tylko tabele w tej samej bazie danych.) Indeksy kluczy obcych mogą być jednak tworzone automatycznie po stronie zarządzanej, jeśli system bazy danych obsługuje takie indeksy.

Sqlite3 :Musi być dołączony do innej domyślnej bazy danych sqlite3 w czasie wykonywania (odpowiedź SQLite - Jak połączyć tabele z różnych baz danych ), najlepiej przez sygnał 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)

Wtedy oczywiście nie jest potrzebny router bazy danych i zwykły django...ForeignKey może być używany z db_constraint=False. Zaletą jest to, że "db_table" nie jest konieczne, jeśli nazwy tabel są unikalne w różnych bazach danych.

W MySQL klucze obce między różnymi bazami danych są łatwe. Wszystkie polecenia, takie jak SELECT, INSERT, DELETE, obsługują dowolne nazwy baz danych bez ich wcześniejszego dołączania.

To pytanie dotyczyło starszych baz danych. Mam jednak kilka interesujących wyników również z migracjami.



  1. Database
  2.   
  3. Mysql
  4.   
  5. Oracle
  6.   
  7. Sqlserver
  8.   
  9. PostgreSQL
  10.   
  11. Access
  12.   
  13. SQLite
  14.   
  15. MariaDB
  1. Laravel 5 PDOException nie może znaleźć sterownika

  2. użyj warunku If else w celu wybrania kolumny w mysql?

  3. mysql Compress() z sqlalchemy

  4. Czy istnieje optymalna metoda zamawiania indeksu złożonego MySQL?

  5. MySQL:wiele tabel czy jedna tabela z wieloma kolumnami?