2016-01-13 43 views
3

在一个芹菜任务中,我需要在数据库中创建临时表。 Daniel Roseman在this article中解释了如何创建一个。但是这个解决方案在Django 1.9中不起作用。我试图研究Django文档和Google,但是我找不到任何有用的东西。从提到的文章django中的临时模型1.9

守则,在Django 1.8工作:

from django.db import models, cursor 
from django.contrib.contenttypes.management import update_contenttypes 
from django.core.management import call_command 

class TempCustomerAddress(models.Model): 
    address = models.ForeignKey('accounts.Address') 
    legacy_id = models.CharField(max_length=12, unique=True) 

    class Meta: 
     app_label = 'utils' 


class Command(NoArgsCommand): 

    def handle_noargs(self, **options): 
     models.register_models('utils', TempCustomerAddress) 
     models.signals.post_syncdb.disconnect(update_contenttypes) 
     call_command('syncdb') 

     # ... do importing and stuff referring to TempCustomerAddress ... 

     cursor = connection.cursor() 
     cursor.execute('DROP TABLE `utils_tempcustomeraddress`') 

回答

2

在Django 1.9你其实并不需要注册任何东西。您只需按照models.py中的相同方式创建模型即可。您只需确保它不在models.py文件中,因为它将成为永久型号。 此示例假定您已经运行了所有迁移。

from django.db import models, cursor 
from django.contrib.contenttypes.management import update_contenttypes 
from django.core.management import call_command 

class TempCustomerAddress(models.Model): 
    address = models.ForeignKey('accounts.Address') 
    legacy_id = models.CharField(max_length=12, unique=True) 

    class Meta: 
     app_label = 'utils' 


class Command(NoArgsCommand): 

    def handle_noargs(self, **options): 
     with connection.cursor() as cursor: 
      cursor.execute('DROP TABLE IF EXISTS utils_tempcustomeraddress') 
      cursor.execute(''' 
       CREATE TABLE utils_tempcustomeraddress (
        id INTEGER PRIMARY KEY NOT NULL, 
        address_id REFERENCES accounts_address (id), 
        legacy_id VARCHAR(12) UNIQUE 
       ); 
      ''' 
      # ... do importing and stuff referring to TempCustomerAddress ... 

      cursor.execute('DROP TABLE `utils_tempcustomeraddress`') 
1

我需要创建从一个“永久”模型推导出一个临时的模型,并使用临时表存储,以避免污染的一个永久的表。经过大量探索,包括一篇关于Django 0.96的文章,它指向Django 1.2和一些old material基于集成到Django的迁移技术的一些新材料,我终于想出了一个可与Django 2.0配合使用的配方。

首先,我需要使用Meta明确指定数据库表名:

model_name = re.sub('[@.]', '_', 'some_string') 

class Meta: 
    app_label = original_model._meta.app_label 
    # 
    # Use the explicit name for the database table. 
    # 
    db_table = '"' + model_name.lower() + '"' 

然后,我通过复制,我从原来需要什么创建的模型类:

attr = {'__module__': __name__, 'Meta': Meta} 
local_fields = [field.name for field in original_model._meta.local_fields] 
for field in original_model._meta.fields: 
    # 
    # Clone only the fields which we need, not forgetting that we only 
    # want one primary key. 
    # 
    clone = field.clone() 
    if field.name in local_fields: 
     local_fields.remove(field.name) 
    else: 
     clone.primary_key = False 
    if not isinstance(field, (db_models.AutoField, db_models.OneToOneField, db_models.ManyToManyField)): 
     attr[field.name] = clone 
new_model = type(model_name, (db_models.Model,), attr) 

硬部分正在追踪如何为模型创建新表格。一旦发现,答案很简单:

from django.db import connection 

with connection.schema_editor() as schema_editor: 
    schema_editor.create_model(new_model) 
+0

我应该说,利用克隆一个deepcopy的字段()不是一个完整的解决方案...这只是一个例子。 deepcopy()保留将复制的字段绑定回原始模型的各种数据。 –

+0

FWIW,事实证明Field.clone()知道如何复制一个字段。答案更新,以反映这一点。 –