获取Django中models所有字段信息,保存Markdown

1,267 阅读1分钟

获取Django中model的字段信息,生成数据字典的脚本,详细注释和讲解后续补充

#!/usr/bin/env python
# author: belingud
import django
import os
import sys
from collections import OrderedDict
from django.apps import apps
from django.db import connection

os.environ.setdefault("DJANGO_SETTINGS_MODULE", "project.settings")
django.setup()

args = sys.argv

models = apps.all_models


def get_app_models(arg: str, all_models: OrderedDict) -> OrderedDict:
    """
    arg is command line first value passed
    """
    return all_models if arg == "all" else all_models[arg]


file_path = args[2] if len(args) == 3 else "fields_detail.md"

if not file_path.endswith(".md"):
    print(
        "the second argument file path has to be a markdown file, now it`s {0}".format(
            file_path
        )
    )
    sys.exit(1)

try:
    arg = args[1]
    all_models = get_app_models(arg, models)
    # all_models is an OrderDict
except IndexError:
    all_models = models.values()

markdown_lines = []

table_name = """\n\n## {0}--{1}\n\n"""
table_header = """| 字段名 | 数据类型 | 允许为空 | PK | 字段说明 |
| ---- | ---- | ---- | --- | ---- |
"""
field_desc_str = "| {0} | {1} | {2} | {3} | {4} |"
new_line_str = "\n"


def get_models_fields() -> None:
    """
    get all models and fields,
    format field description into field_desc_str
    and write in file fields_detail.md by default
    if given a specific app name, and file name,
    write fields into a specific file
    :return:
    :rtype:
    """
    for model_odict in all_models:
        for model in model_odict.values():
            markdown_lines.append(table_name.format(model.__name__, model._meta.db_table))
            fields_list = model._meta.get_fields()
            markdown_lines.append(table_header)
            for field in fields_list:
                field_name = field.name
                field_type = field.db_type(connection)
                field_null = field.null
                try:
                    field_limit = field.primary_key
                except AttributeError:
                    field_limit = False
                try:
                    field_verbose = field.verbose_name
                except AttributeError:
                    field_verbose = " "
                _field_str = field_desc_str.format(
                    str(field_name),
                    str(field_type),
                    str(field_null),
                    str(field_limit),
                    str(field_verbose),
                )
                print("_field_str: ", _field_str, end=new_line_str)
                markdown_lines.append(_field_str + new_line_str)
            markdown_lines.append(new_line_str * 2)


def write_to_md(file_path: str) -> None:
    """
    write fields detail into a markdown file,
    file_path could be specific
    :param file_path:
    :type file_path:
    :return:
    :rtype:
    """
    with open(file_path, "w") as fp:
        print("prepare to write markdown file")
        print(len(markdown_lines))
        fp.writelines(markdown_lines)


usage = """
usage:
$ python model_fields.py
---> fields_detail.md
$ python model_fields.py api_home
---> fields_detail.md  # include all models in api_home module
$ python models_fields.py all ~/docs/model_field.md
---> ~/docs/model_field.md  # include all models and output a specific markdown file
$ python model_fields.py company company_models.md
---> company_models.md  # include all models in company models
     and output a specific markdown file
"""


def main(file_path: str) -> None:
    """
    run this function by default,
    will call the get and write method
    :param file_path:
    :type file_path:
    :return:
    :rtype:
    """
    get_models_fields()
    write_to_md(file_path)


if __name__ == "__main__":
    if sys.argv[1] in ("-h", "--help"):
        print(usage)
        sys.exit(1)
    main(file_path)