2010-10-11 66 views
3

我一直在寻找一种方法来定义数据库表并通过Django API修改它们。Django按需创建/更改表

例如,我想编写一些直接操作表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语句,但这种解决方案缺乏治疗数据库作为对象的能力)

只是好奇,如果人们有任何建议或接近这一点。 ..

回答

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进行连接。

+0

OmerGertel,谢谢你的这种做法。我必须深入研究,看看我能否按照你的建议扩展它来改变。我的梦想是让Django(或者至少我的扩展)能够支持“创建,修改,截断等”。我认为它会为它开辟一个全新的使用领域。再次感谢您的意见和想法。 – 2010-10-15 14:27:16

2

赶紧把我的头顶部..

与创建/更改方法创建自定义管理器。

+1

谢谢你的建议,Rasiel。我想我希望我不必将SQL硬编码到管理器或类似的东西中。毕竟,如果syncdb可以发出CREATE语句,可以希望手动调用它。但是,也许在Django中使用SQL DDL是大多数人不想做的事情。 – 2010-10-12 00:50:11