概要
実装されているモデルのテーブル定義とER図を参照できる view を作成します.
注)テーブル定義は MySQL のみ対応です.
環境
- Django 2.1
- MySQL 5.7 (ER図の方は無くても可)
サンプルコード
ここの db_info
app にて実装.
ER図の出力には graphviz などが必要になるので Dockerfile も参考になるかもです.
コード
テーブル定義
mysqldump
をつかって定義を出力し, それを xsltproc
で html に変換したものをレスポンスにします.
参考: https://qiita.com/mamy1326/items/c0aa9252d61ffed31a6e
class TableView(View):
tmp_dir = None
# TODO: 出力関連のコードを別モジュールに移動
def get_target_app_configs(self) -> List[AppConfig]:
targets = ['users', 'articles']
return [config for config in apps.app_configs.values() if config.name in targets]
def get_style_file(self):
return os.path.join(settings.STATIC_ROOT, 'db_info/style.xsl')
def get_target_tables(self) -> List[str]:
"""
app 内のすべてのモデルの table を取得
"""
configs = self.get_target_app_configs()
tables = []
for app_config in configs:
for model_name, model in app_config.models.items():
tables.append(model._meta.db_table)
return tables
def output_table_info_from_mysql(self) -> str:
"""
mysqldump を使ってテーブル定義の xml ファイルを出力
Returns: file name
"""
db_info = settings.DATABASES['default']
cmd_params = [
'mysqldump',
'--no-data',
'--xml',
f'--user={db_info["USER"]}',
f'--password={db_info["PASSWORD"]}',
f'--host={db_info["HOST"]}',
db_info['NAME'],
'--tables',
]
cmd_params += self.get_target_tables()
file_name = os.path.join(self.tmp_dir, 'spam.xml')
with open(file_name, 'wb') as f:
popen = subprocess.Popen(cmd_params, stdout=f)
popen.wait()
return file_name
def run_convert_xml_to_html(self, xml_path):
html_path = os.path.join(self.tmp_dir, 'spam.html')
cmd_params = [
'xsltproc',
'--output', html_path,
self.get_style_file(),
xml_path
]
subprocess.run(cmd_params)
return html_path
def get_table_layout(self):
xml_path = self.output_table_info_from_mysql()
return self.run_convert_xml_to_html(xml_path)
def get(self, request):
with tempfile.TemporaryDirectory() as d:
self.tmp_dir = d
html_file = self.get_table_layout()
response = HttpResponse(File(open(html_file, 'rb')), content_type='text/html')
return response
static ファイルを参照するので, お試しする場合は事前に python manage.py collectstatic
必要です.
ER図
django-extensions の graph_models
を使って ER 図を pdf に出力したものをレスポンスにします.
class GraphModelsView(View):
# TODO: 出力関連のコードを別モジュールに移動
def get_target_app_names(self) -> List[str]:
return ['accounts', 'articles']
def get_options(self):
return {
'exclude_models': ['Permission', ],
'exclude_columns': ['created_at', 'updated_at'],
'verbose_names': True,
'group_models': True,
'disable_sort_fields': True,
}
def get(self, request): target_apps = self.get_target_app_names()
with tempfile.TemporaryDirectory() as d:
fpath = os.path.join(d, 'spam.pdf')
kwargs = self.get_options()
kwargs.update({
'outputfile': fpath
})
call_command('graph_models', *target_apps, **kwargs)
response = HttpResponse(File(open(fpath, 'rb')), content_type='application/pdf')
response['Content-Disposition'] = f'inline; filename=er-diagram.pdf'
return response
補足
subprocess
をちゃんと理解せず使っているのでおかしなところあるかも.エラー処理をいれていないので,
subprocess
でエラーになったりするとどうなるかわかんないです><
つかってみる
サンプルコードの Django サーバーを起動し
- /db_info/table
- /db_info/graph
にアクセスすると以下の図のように表示されます.
テーブル定義
論理名欄にはフィールドのコメントが出力されます.
本サンプルでは事前に前回記事 のコマンドを実行しています.
このコマンドはサンプルに今回と同じ db_info
app に入れています.
ER 図
おわりに
Django モデルのテーブル定義とER図を参照できる View を作成しました.
開発中の最新のモデルの確認・共有ができるのでいいんじゃないでしょうか.