Mysql
 sql >> Teknologi Basis Data >  >> RDS >> Mysql

Kunci Asing Django dalam skema lain

Saya telah mencoba menggunakan dua database untuk mensimulasikan kasus Anda, dan temukan solusinya di bawah ini:

1. Skenario:

  1. basis data schema1 , yang dikelola oleh Django (baca &tulis)
  2. basis data schema2 , yaitu TIDAK dikelola oleh django

2. Langkah-langkah:

  1. buat migrasi python manage.py makemigrations untuk model Anda
  2. Buat SQL untuk migrasi Anda:python manage.py sqlmigrate app 0001 .(misalkan nama file migrasi yang dihasilkan adalah 0001_initial.py dari langkah 1 )

Sql untuk migrasi ini akan terlihat seperti ini:

CREATE TABLE `user_info` (`id_id` integer NOT NULL PRIMARY KEY, `name` varchar(20) NOT NULL);
ALTER TABLE `user_info` ADD CONSTRAINT `user_info_id_id_e8dc4652_fk_schema2.user_extra_info_id` FOREIGN KEY (`id_id`) REFERENCES `user_extra_info` (`id`);
COMMIT;

Jika Anda menjalankan sql di atas secara langsung, Anda akan berakhir dengan kesalahan seperti ini:

django.db.utils.OperationalError: (1824, "Failed to open the referenced table 'user_extra_info'")

Itu karena django mengasumsikan bahwa semua langkah migrasi Anda dijalankan dalam database yang sama . Jadi tidak bisa mengetahui user_extra_info di schema1 basis data.

3. Langkah-Langkah Berikut:

  1. Tentukan secara eksplisit database schema2 untuk tabel user_extra_info :

    ALTER TABLE `user_info` ADD CONSTRAINT `user_info_id_id_e8dc4652_fk_schema2.user_extra_info_id` FOREIGN KEY (`id_id`) REFERENCES schema2.user_extra_info (`id`);
    
  2. Jalankan sql yang direvisi secara manual di schema1 basis data.

  3. Beri tahu Django bahwa saya telah menjalankan migrasi sendiri:python manage.py migrate --fake

  4. Selesai!!

Kode sumber Untuk referensi Anda:

models.py

from django.db import models


class UserExtraInfo(models.Model):
    # table in schema2, not managed by django
    name = models.CharField('name', max_length=20)

    class Meta:
        managed = False
        db_table = 'user_extra_info'


class UserInfo(models.Model):
    # table in schema1, managed by django
    id = models.OneToOneField(
        UserExtraInfo,
        on_delete=models.CASCADE,
        primary_key=True
    )
    name = models.CharField('user name', max_length=20)

    class Meta:
        db_table = 'user_info'

settings.py

# Database
# https://docs.djangoproject.com/en/2.1/ref/settings/#databases

DATABASES = {
    'default': {
        'ENGINE': 'django.db.backends.mysql',
        'NAME': 'schema1',
        'USER': 'USER',
        'PASSWORD': 'PASSWORD',
        'HOST': 'localhost',
        'PORT': 3306,
    },
    'extra': {
        'ENGINE': 'django.db.backends.mysql',
        'NAME': 'schema2',
        'USER': 'USER',
        'PASSWORD': 'PASSWORD',
        'HOST': 'localhost',
        'PORT': 3306,
    }
}

DATABASE_ROUTERS = ['two_schemas.router.DBRouter']

router.py

class DBRouter(object):
    """
    A router to control all database operations on models in the
    auth application.
    """
    def db_for_read(self, model, **hints):
        """
        Attempts to read auth models go to auth_db.
        """
        if model._meta.db_table == 'user_extra_info':
            # specify the db for `user_extra_info` table
            return 'extra'
        if model._meta.app_label == 'app':
            return 'default'
        return None

    def db_for_write(self, model, **hints):
        """
        Attempts to write auth models go to auth_db.
        """
        if model._meta.db_table == 'user_extra_info':
            # specify the db for `user_extra_info` table
            return 'extra'
        if model._meta.app_label == 'app':
            return 'default'
        return None

    def allow_relation(self, obj1, obj2, **hints):
        """
        Relations between objects are allowed if both objects are
        in the primary/replica pool.
        """
        db_list = ('default', 'extra')
        if obj1._state.db in db_list and obj2._state.db in db_list:
            return True
        return None

    def allow_migrate(self, db, app_label, model_name=None, **hints):
        """
        Make sure the auth app only appears in the 'auth_db'
        database.
        """
        if app_label == 'app':
            return db == 'default'
        return None


  1. Database
  2.   
  3. Mysql
  4.   
  5. Oracle
  6.   
  7. Sqlserver
  8.   
  9. PostgreSQL
  10.   
  11. Access
  12.   
  13. SQLite
  14.   
  15. MariaDB
  1. Cara terbaik untuk membangun mesin pencari mySQL &PHP SMART?

  2. MySQL - NULL aman BUKAN operator yang sama

  3. Menyimpan array dengan panjang yang tidak diketahui

  4. Laravel 5:jalankan migrasi di lingkungan server, bukan lokal

  5. Praktik terbaik untuk menyimpan informasi bank dalam database