Multiple databases

Khi xây dựng một cở sở dữ liệu cho ứng dụng của bạn đa phần dữ liệu của bạn là dữ liệu động và nó sẽ thay đổi thường xuyên sau những request của user, sau một thời gian sử dụng dữ liệu của bạn sẽ dần lớn lên. Để thuận tiện cho việc quản lý ta thường chia nhỏ cơ sở dữ liệu. Trong bài này mình sẽ hướng dẫn việc tương tác giữa nhiều cơ sở dữ liệu.

Defining your databases

Bước đầu tiên để sử dụng nhiều hơn một database với Django bạn phải định nghĩa database mà bạn sử dụng. Nó được định nghĩa trong setting, trong ví dụ dưới đây mình định nghĩa 2 cơ sở dữ liệu, ở đây mình dùng engine MySQL:

DATABASES = {
    'default': {},
    'users': {
        'NAME': 'user_data',
        'ENGINE': 'django.db.backends.mysql',
        'USER': 'mysql_user',
        'PASSWORD': 'superS3cret'
    },
    'customers': {
        'NAME': 'customer_data',
        'ENGINE': 'django.db.backends.mysql',
        'USER': 'mysql_cust',
        'PASSWORD': '[email protected]'
    }
}

Synchronizing your databases

Để migrate database của bạn chạy lệnh migrate có chỉ định database tương ứng. Như ví dụ trên ta sử dụng 2 databases: users và customers. Vậy để đồng bộ tất cả models vào cở sở dữ liệu của bạn bạn cần chạy 2 lệnh migrate sau:

python migrate --database=users
python migrate --database=customers

Chú ý: nếu models của bạn thay đổi hoặc thêm mới thì trước khi migrate bạn cần thực hiện việc cập nhật lại thông tin migrate của nó. Bạn sử dụng lệnh makemigrations.

Automatic database routing

Cách đơn giản nhất để có thể sử dụng multiple databases đó là chúng ta thiết lập một sơ đồ định tuyến cho nó (routing). Routing đảm bảo cho các đối tượng sẽ được truy cập đúng database được chỉ định. Trong trường hợp database đó không được định nghĩa thì những truy cập đấy sẽ được chỉ định với default database.

Một database Router là một class cung cấp cho bạn 4 phương thức: db_for_read(model, hints) Get database tương ứng với model. Trường hợp ngoại lệ không thoả mãn yêu cầu bạn có thể return về None. Ví dụ:

    if model._meta.app_label == 'abc':
         return 'user_data'
    return None

db_for_write(model, **hints) Ghi model vào trong database. Trường hợp không thoả mãn yêu cầu thì return None. Ví dụ:

    if model._meta.app_label == 'xxx':
        return 'customer_data'
    return None

allow_relation(obj1, obj2, **hints) Return True nếu mối quan hệ giữa 2 object là được phép. Ví dụ: Khi bạn chắc chắn rằng customer chỉ xuất hiện trên app xxx.

 def allow_syncdb(self, db, model):
        if db == 'customer_data':
            return model._meta.app_label == 'xxx'
        return False

allow_migrate(db, app_label, model_name=None, **hints) Định nghĩa các rule cho phép migrate Ví dụ: Để dảm bảo user chỉ được migrate trên user_data database

if app_label == 'abc':
            return db == 'user_data'
        return None

Using router

Để sử dụng được router. Trong file setting.py bạn cần định nghĩa thêm DATABASE_ROUTERS.

DATABASE_ROUTERS = ['path.to.router']

Manually selecting a database

Django cũng cung cấp cho bạn một API cho phép bạn có thể update database trong code của bạn thay vì sử dụng route. Ví dụ để lấy toàn bộ user trong user_data.

User.objects.using('user_data').all()

Lưu lại model vào trong database

my_object.save(using='user_data')

Chốt

Trong bài này minh đã giới thiệu cho các bạn cách setting multiple database trong Django. Tuy nhiên khi sử dụng chúng ta cần chú ý:

  • User, Group and Permission thường đc liên kết vơi nhau lên store trong một database.
  • Admin cũng phụ thuộc vào authentication lên cũng lên được store cùng user, group and permission.
  • Khi bạn đồng bộ hóa các loại nội dung với nhiều cơ sở dữ liệu, hãy lưu ý rằng các khóa chính của chúng có thể không khớp với các cơ sở dữ liệu. Điều này có thể dẫn đến hỏng dữ liệu hoặc mất dữ liệu. Hãy nhớ backup data trước khi thực hiện việc đồng bộ hoá.