Django按需创建/更改表

时间:2010-10-11 20:58:07

标签: django ddl alter

我一直在寻找一种定义数据库表的方法,并通过Django API来改变它们。

例如,我想编写一些直接操作表DDL的代码,并允许我以编程方式定义表或按需添加列(不运行syncdb)。我意识到django-south和django-evolution可能会浮现在脑海中,但我并不认为这些工具可以作为工具集成到应用程序中并由最终用户使用...而是这些工具是用于升级数据库表。我正在寻找能做类似事情的事情:

class MyModel(models.Model):  # wouldn't run syncdb.. instead do something like below
    a = models.CharField()
    b = models.CharField()

model = MyModel()
model.create()  # this runs the create table (instead of a syncdb)

model.add_column(c = models.CharField())  # this would set a column to be added
model.alter()   # and this would apply the alter statement 

model.del_column('a')   # this would set column 'a' for removal 
model.alter()   # and this would apply the removal 

这只是一个关于这样一个API如何工作的玩具示例,但关键是我很想知道是否有一种方法以编程方式创建和更改这样的表。这对于诸如内容管理系统之类的东西可能是有用的,其中人们可能想要动态地创建新表。另一个示例是存储任意宽度的数据集的站点,对于这些数据集,需要通过接口或数据导入动态生成表。任何人都知道任何动态创建和更改这样的表的好方法吗?

(当然,我知道可以对数据库执行直接的SQL语句,但该解决方案缺乏将数据库视为对象的能力)

只是好奇人们是否有任何建议或方法......

2 个答案:

答案 0 :(得分:2)

快速脱离我的头顶..

使用Create / Alter方法创建自定义管理器。

答案 1 :(得分:1)

您可以尝试与管理数据库更改的django代码进行交互。它有点受限(例如,就我所见,没有ALTER),但您可以扩展它。这是django.core.management.commands.syncdb的摘录。

for app in models.get_apps():
        app_name = app.__name__.split('.')[-2]
        model_list = models.get_models(app)
        for model in model_list:
            # Create the model's database table, if it doesn't already exist.
            if verbosity >= 2:
                print "Processing %s.%s model" % (app_name, model._meta.object_name)
            if connection.introspection.table_name_converter(model._meta.db_table) in tables:
                continue
            sql, references = connection.creation.sql_create_model(model, self.style, seen_models)
            seen_models.add(model)
            created_models.add(model)
            for refto, refs in references.items():
                pending_references.setdefault(refto, []).extend(refs)
                if refto in seen_models:
                    sql.extend(connection.creation.sql_for_pending_references(refto, self.style, pending_references))
            sql.extend(connection.creation.sql_for_pending_references(model, self.style, pending_references))
            if verbosity >= 1 and sql:
                print "Creating table %s" % model._meta.db_table
            for statement in sql:
                cursor.execute(statement)
            tables.append(connection.introspection.table_name_converter(model._meta.db_table))

看看connection.creation.sql_create_modelcreation对象是在与您在settings.py中使用的数据库相关的数据库后端中创建的。所有这些都在django.db.backends下。

如果您必须拥有ALTER表,我认为您可以创建自己的自定义后端,扩展现有的后端并添加此功能。然后,您可以通过您创建的ExtendedModelManager直接与它进行交互。