Mysql
 sql >> Cơ Sở Dữ Liệu >  >> RDS >> Mysql

Khóa ngoại Django trong một lược đồ khác

Tôi đã cố gắng sử dụng hai cơ sở dữ liệu để mô phỏng trường hợp của bạn và tìm ra giải pháp bên dưới:

1. Tình huống:

  1. cơ sở dữ liệu schema1 , được quản lý bởi django (đọc và ghi)
  2. cơ sở dữ liệu schema2 , cái nào KHÔNG do django quản lý

2. Các bước:

  1. tạo di chuyển python manage.py makemigrations cho các mô hình của bạn
  2. Tạo SQL để di chuyển của bạn:python manage.py sqlmigrate app 0001 . ( giả sử tên tệp di chuyển được tạo là 0001_initial.py từ bước 1 )

Sql cho quá trình di chuyển này sẽ giống như sau:

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;

Nếu bạn chạy trực tiếp sql ở trên, bạn sẽ gặp lỗi như sau:

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

Đó là bởi vì django giả định rằng tất cả các bước di chuyển của bạn đều được thực thi trong cùng một cơ sở dữ liệu . Vì vậy, nó không thể tìm ra user_extra_info trong schema1 cơ sở dữ liệu.

3. Các bước sau:

  1. Chỉ định rõ ràng cơ sở dữ liệu schema2 cho bảng 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. Chạy thủ công sql đã sửa đổi trong schema1 cơ sở dữ liệu.

  3. Nói với django rằng tôi đã tự mình chạy quá trình di chuyển:python manage.py migrate --fake

  4. Xong !!

Mã nguồn Để bạn tham khảo:

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. Bạn có thể chia một bí danh này cho một bí danh khác trong MySQL không?

  2. Làm thế nào để tạo tệp pdf với dữ liệu mysql?

  3. TRIGGER khiến INSERT không thành công? Có thể được?

  4. Truy vấn SELECT này mất 180 giây để hoàn thành

  5. Làm thế nào để Chèn Giá trị NULL từ Biến PHP sang MySQL, tránh xa SQL Injection?