iT邦幫忙

2022 iThome 鐵人賽

DAY 6
0

Day6 設計格局,Django 多租戶架構

你也想成為房屋改造大師嗎?或許在現實有點困難,但我們將 Django 變身為多租戶架構卻很容易,今天讓我們來一探究竟吧!

目錄結構

首先來看看我們目前的目錄結構,現在我們的 web 目錄為 ./example_tenant

.
├── data                          # 資料存放目錄
│   └── postgres
│       └── data
├── docker-compose.yml            # docker compose 設定檔
├── docker-entrypoint.sh          # entry-point    設定檔
├── Dockerfile                    # Dockerfile
├── web                           # Django 專案主目錄
│   ├── db.sqlite3                # Django 原生 Database SQLite
│   ├── main                      # Django 主要應用程式
│   │   ├── asgi.py
│   │   ├── __init__.py
│   │   ├── settings.py           # Django 主設定檔
│   │   ├── urls.py
│   │   └── wsgi.py
│   └── manage.py                 # Django command-line 命令程式
└── requirements.txt              # python 套件清單

Django 主設定擋

settings.py 為 Django 的主設定擋,我們將調整設定與參數來架設我們的多租戶架構

設定資料庫引擎,使用我們已經安裝的 postgresql 與其設定,這裡的 host 會對應到 docker-compose.yml 中的 service name

# settings.py

DATABASES = {
    'default': {
        'ENGINE': 'django_tenants.postgresql_backend',
        'NAME': 'db_name',
        'USER': 'db_user',
        'PASSWORD': 'db_password',
        'HOST': 'db',
        'PORT': '5432',
        'TIME_ZONE': 'Asia/Taipei',
    }
}

設定資料庫路由器

# settings.py

DATABASE_ROUTERS = (
    'django_tenants.routers.TenantSyncRouter',
)

新增 middleware

# settings.py

MIDDLEWARE = (
    'django_tenants.middleware.main.TenantMainMiddleware',
    #...
)

新增 context_processors

# settings.py

TEMPLATES = [
    {
        #...
        'OPTIONS': {
            'context_processors': [
                'django.template.context_processors.request',
                #...
            ],
        },
    },
]

租戶共享應用程式

建立應用程式來管理我們的租戶,這裡將新增一個 應用程式(app)與模型(model),細節會放到後續的文章會再詳細講解。

docker exec 指令可以在容器中運行一個新命令

docker exec [OPTIONS] CONTAINER COMMAND [ARG...]

--workdir 指定運行的目錄

新增 customers 應用程式

docker exec --workdir /opt/app/web example_tenant_web \
python3.10 manage.py startapp customers

建立租戶模型 models.py ,這裡需要繼承 TenantMixin 與 DomainMixin,其他欄位可以自行新增。

這裡新增兩個模型 Client (租戶)與 domain(網域)

# customers/models.py

from django.db import models
from django_tenants.models import TenantMixin, DomainMixin

class Client(TenantMixin):
    name = models.CharField(max_length=100)
    paid_until =  models.DateField()
    on_trial = models.BooleanField()
    created_on = models.DateField(auto_now_add=True)

    # default true, schema will be automatically created and synced when it is saved
    auto_create_schema = True

class Domain(DomainMixin):
    pass

建立管理介面,Django 自帶管理介面,只要建立了 model 則可以快速生成管理介面。

# cuustomers/admin.py

from django.contrib import admin
from django_tenants.admin import TenantAdminMixin

from customers.models import Client

@admin.register(Client)
class ClientAdmin(TenantAdminMixin, admin.ModelAdmin):
        list_display = ('name', 'paid_until')

設定租戶與共享應用程式

INSTALLED_APPS 是 Django 設定應用程式的列表。在建立應用程式之後通常就會使用此列表加入到專案中。

而在多租戶架構下,我們可以自行設定要租戶共享的應用程式 SHARED_APPS 與租戶獨自擁有的應用程式 TENANT_APPS。

# settings.py

# Application definition

SHARED_APPS = (
    'django_tenants',  # mandatory
    'customers', # you must list the app where your tenant model resides in
    'django.contrib.contenttypes',
)

TENANT_APPS = (
    'django.contrib.auth',
    'django.contrib.sessions',
    'django.contrib.sites',
    'django.contrib.messages',
    'django.contrib.staticfiles',
    'django.contrib.admin',
    'django.contrib.sitemaps',
)

INSTALLED_APPS = list(SHARED_APPS) + [app for app in TENANT_APPS if app not in SHARED_APPS]

設定站台。因為將 Django 自帶的管理介面設定為租戶獨享,會無法取得預設站台,這裡要先指定預設站台

# settings.py

SITE_ID = 1

設定租戶與模型的位置

# settings.py

TENANT_MODEL = "customers.Client" # app.Model

TENANT_DOMAIN_MODEL = "customers.Domain"  # app.Model

多租戶架構的設置到這裡就大致完成了,最後一步則是遷移資料庫。

遷移資料庫

有了模型後要如何讓資料庫生成資料表呢?遷移指令是 Django 將 model 應用至資料庫結構中的方式。

基本指令如下

migrate         # 負責應用遷移
makemigrations  # 根據模型建立遷移檔案
sqlmigrate      # 列出遷移時使用的 SQL 語法
showmigrations  # 列出遷移狀態

而 django-tenant 額外提供只遷移 SHARED_APPS 的語法

migrate_schemas --shared # 應用 SHARED_APPS  

而使用 migrate 則將同時作用於 SHARED_APPS 與 TENANT_APPS。

現在讓我們開始進行遷移吧!

建立遷移檔案

docker exec --workdir /opt/app/web example_tenant_web \
    python3.10 manage.py makemigrations

...

Migrations for 'customers':
  customers/migrations/0001_initial.py
    - Create model Client
    - Create model Domain

應用遷移

docker exec --workdir /opt/app/web example_tenant_web \
    python3.10 manage.py migrate

...

=== Starting migration
Operations to perform:
  Apply all migrations: admin, auth, contenttypes, customers, sessions, sites
Running migrations:
  Applying customers.0001_initial...
 OK

大功告成!

最後查看一下當前的資料庫結構,由於還沒有建立租戶,所以只有 SHARED_APPS 在 pubic schema 生成的資料表如下:

 Schema |        Name         | Type  |  Owner  
--------+---------------------+-------+---------
 public | customers_client    | table | db_user
 public | customers_domain    | table | db_user
 public | django_content_type | table | db_user
 public | django_migrations   | table | db_user
(4 rows)

專案目錄結構:

.
├── data
│   └── postgresql
│       └── data
├── docker-compose.yml
├── docker-entrypoint.sh
├── Dockerfile
├── LICENSE
├── README.md
├── requirements.txt
└── web
    ├── customers
    │   ├── admin.py
    │   ├── apps.py
    │   ├── __init__.py
    │   ├── migrations
    │   ├── models.py
    │   ├── tests.py
    │   └── views.py
    ├── db.sqlite3
    ├── main
    │   ├── asgi.py
    │   ├── __init__.py
    │   ├── settings.py
    │   ├── urls.py
    │   └── wsgi.py
    └── manage.py

Django 的多租戶架構變身成功!明天我們將請第一個房客入住,『第一個房客,建立租戶』


上一篇
Day5 蓋一棟 Django 小屋
下一篇
Day7 第一個房客,建立租戶
系列文
全能住宅改造王,Django 多租戶架構的應用 —— 實作一個電商網站30
圖片
  直播研討會
圖片
{{ item.channelVendor }} {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言