2016-01-13 200 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()知道如何複製一個字段。答案更新,以反映這一點。 –