Django:如何获取项目中每个表及其所有列?

3 投票
3 回答
18409 浏览
提问于 2025-04-16 01:01

我正在用MySQL的INTO OUTFILE和LOAD DATA LOCAL INFILE来创建一套完整的数据库复制脚本。

具体来说:

SELECT {columns} FROM {table} INTO OUTFILE '{table}.csv'

LOAD DATA LOCAL INFILE '{table}.csv' REPLACE INTO {table} {columns}

所以,我不仅需要表格,还需要表格中的列。

我可以获取所有的表和列,但这不包括多对多(m2m)表:

from django.db.models import get_models()
for model in get_models():
    table = model._meta.db_table
    columns = [field.column for field in model._meta.fields]

我也可以获取所有的表,但这并不能让我访问到列:

from django.db import connection
tables = connection.introspection.table_names()

在一个Django项目中,如何获取每个表及其对应的所有列呢?

更多细节:

我正在处理一个相对较大的数据集(超过1GB),所以使用平面文件的方法似乎是唯一合理的方式来在MySQL中进行这么大的复制。我已经把数据库结构复制过来了(使用./manage.py syncdb --migrate),我现在遇到的问题主要是复制数据,这需要我有表和列的信息,以便创建正确的SQL语句。另外,我不能使用默认的列顺序,因为我复制的生产数据库的列顺序与新建的syncdb生成的顺序不同(这主要是因为经过了几个月的迁移和结构变化)。

3 个回答

0

你有没有了解过“manage.py dumpdata”和“manage.py loaddata”?这两个命令可以把数据导出和导入,格式是json。 我用它来把一个网站的数据导出来,然后覆盖到另一个网站的数据库里。虽然在dumpdata的时候没有“导出所有数据库”的选项,但你可以在“manage.py dbshell”命令的结果上用循环来调用它。

5

你有没有看过 manage.py 这个文件?

你可以获取很多关于SQL的信息,比如说,如果你想要查看你项目中某个应用的所有创建表的语法,你可以这样做:

python manage.py sqlall <appname>

如果你输入:

python manage.py help

你会发现还有很多其他的功能。

4

我深入研究了源代码,找到了这个解决方案。我觉得可能还有更好的方法,但这个方法可以解决问题。

第一个代码块获取了所有普通的(非多对多)表及其列。

from django.db import connection
from django.apps import apps

table_info = []
tables = connection.introspection.table_names()
seen_models = connection.introspection.installed_models(tables)
for model in apps.get_models():
    if model._meta.proxy:
        continue

    table = model._meta.db_table
    if table not in tables:
        continue

    columns = [field.column for field in model._meta.fields]
    table_info.append((table, columns))

接下来的代码块是比较棘手的部分。它获取了所有多对多字段的表及其列。

for model in apps.get_models():
    for field in model._meta.local_many_to_many:
        if not field.creates_table:
            continue

        table = field.m2m_db_table()
        if table not in tables:
            continue
        columns = ['id'] # They always have an id column
        columns.append(field.m2m_column_name())
        columns.append(field.m2m_reverse_name())
        table_info.append((table, columns))

撰写回答