django 中的临时模型
Temporary models in django
在一个 celery 任务中,我需要在数据库中创建临时 table。在 this article 中,Daniel Roseman 解释了如何创建一个。但是这个解决方案在 Django 1.9 中不起作用。我试图查看 Django 文档和 Google 但我找不到任何有用的东西。
上述文章中可在 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`')
在 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`')
我需要创建一个从 "permanent" 模型派生的临时模型,并使用临时 table 存储以避免污染永久模型的 table。经过大量探索,包括一篇与 Django 0.96, some newer material it points to for Django 1.2 and some old material 有关的文章,该文章基于集成到 Django 中的迁移技术,我终于想出了一个适用于 Django 2.0 的方法。
首先,我需要使用 Meta:
显式指定数据库 table 名称
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() + '"'
然后我通过复制我需要的原始模型创建了模型class:
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)
困难的部分是追踪如何为模型创建新的 table。一旦找到,答案很简单:
from django.db import connection
with connection.schema_editor() as schema_editor:
schema_editor.create_model(new_model)
在一个 celery 任务中,我需要在数据库中创建临时 table。在 this article 中,Daniel Roseman 解释了如何创建一个。但是这个解决方案在 Django 1.9 中不起作用。我试图查看 Django 文档和 Google 但我找不到任何有用的东西。
上述文章中可在 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`')
在 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`')
我需要创建一个从 "permanent" 模型派生的临时模型,并使用临时 table 存储以避免污染永久模型的 table。经过大量探索,包括一篇与 Django 0.96, some newer material it points to for Django 1.2 and some old material 有关的文章,该文章基于集成到 Django 中的迁移技术,我终于想出了一个适用于 Django 2.0 的方法。
首先,我需要使用 Meta:
显式指定数据库 table 名称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() + '"'
然后我通过复制我需要的原始模型创建了模型class:
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)
困难的部分是追踪如何为模型创建新的 table。一旦找到,答案很简单:
from django.db import connection
with connection.schema_editor() as schema_editor:
schema_editor.create_model(new_model)