如何将一个Django应用中的模型迁移至另一个新的应用中?
如果你想将一个Django模型从一个app迁移到另一个app,这个过程非常简单。Django中的模型与app之间的耦合度并不高,因此迁移相对容易。在Django中,数据库表的名称中包含了app的名称,所以如果你想移动你的app,你可以通过SQL的ALTER TABLE
语句来重命名数据库表,或者更简单地,在你的模型的Meta
类中使用db_table
参数来引用旧名称。
如果你的代码中使用了ContentTypes或者通用关系(generic relations),你可能需要重命名指向正在移动的模型的contenttype的app_label
,以保留现有的关系。
当然,如果你不需要保留任何数据,最简单的方法就是完全删除数据库表,并再次运行./manage.py syncdb
。
那么,如何通过south迁移来实现呢?
如何使用south进行迁移。
假设我们有两个应用程序:common和specific:
myproject/
|-- common
| |-- migrations
| | |-- 0001_initial.py
| | `-- 0002_create_cat.py
| `-- models.py
`-- specific
|-- migrations
| |-- 0001_initial.py
| `-- 0002_create_dog.py
`-- models.py
现在我们想要将common.models.cat模型移动到specific应用程序(精确地说是specific.models.cat)。
首先在源代码中进行更改,然后运行:
$ python manage.py schemamigration specific create_cat --auto
+ Added model 'specific.cat'
$ python manage.py schemamigration common drop_cat --auto
- Deleted model 'common.cat'
myproject/
|-- common
| |-- migrations
| | |-- 0001_initial.py
| | |-- 0002_create_cat.py
| | `-- 0003_drop_cat.py
| `-- models.py
`-- specific
|-- migrations
| |-- 0001_initial.py
| |-- 0002_create_dog.py
| `-- 0003_create_cat.py
`-- models.py
现在我们需要编辑两个迁移文件:
#0003_create_cat: 替换现有的前向和后向代码
#只使用一句话:
def forwards(self, orm):
db.rename_table('common_cat', 'specific_cat')
if not db.dry_run:
# 为了在迁移后正常工作的权限
orm['contenttypes.contenttype'].objects.filter(
app_label='common',
model='cat',
).update(app_label='specific')
def backwards(self, orm):
db.rename_table('specific_cat', 'common_cat')
if not db.dry_run:
# 为了在迁移后正常工作的权限
orm['contenttypes.contenttype'].objects.filter(
app_label='specific',
model='cat',
).update(app_label='common')
#0003_drop_cat: 替换现有的前向和后向代码; 添加依赖项:
depends_on = (
('specific', '0003_create_cat'),
)
def forwards(self, orm):
pass
def backwards(self, orm):
pass
现在两个应用程序的迁移都知道了变化,生活变得稍微好一点 🙂
建立迁移之间的这种关系是成功的关键。
现在,如果您执行:
python manage.py migrate common
> specific: 0003_create_cat
> common: 0003_drop_cat
将进行两个迁移,而且
python manage.py migrate specific 0002_create_dog
< common: 0003_drop_cat
< specific: 0003_create_cat
会进行迁移。
请注意,升级模式时我使用了common应用程序,而降级时我使用了specific应用程序。这是因为依赖关系的工作方式。
您可能还需要对django_content_type表进行数据迁移。
如果您将模型从内部项目的一个应用程序移动到外部项目中(其他用户将期望有一个初始迁移),您还可以在drop_cat中进行重命名,并在新应用程序中伪造初始迁移。
非常好的指南。我很好奇,0003_create_cat
的后向部分中是否也应该有orm['contenttypes.contenttype'].objects.filter
行?另外,我想分享一个提示。如果你有索引,它们也需要修改。在我的情况下,它们是唯一的索引,所以我的前向看起来像这样:db.delete_unique('common_cat', ['col1'])
db.rename_table('common_cat', 'specific_cat')
db.delete_unique('specific_cat', ['col1'])
为了访问orm['contenttypes.contenttype']
,您还需要在schemamigration
命令中添加--freeze contenttypes
选项。
如果您使用自定义AUTH模型来自django 1.5,则需要在settings.py
中更改AUTH_USER_MODEL = 'specific.User'
在我的情况下(Django 1.5.7和South 1.0)..我必须输入python manage.py schemamigration specific create_cat --auto --freeze common
才能访问来自common应用程序的cat模型。
在django 1.8中不起作用:unknown command schemamigration
自2016年以来,South已经停止更新!
如何将模型从一个Django应用程序迁移到新的应用程序?
有时,涉及外键的情况更加复杂,需要稍微不同的处理方式。
假设我们有两个应用程序common和specific,其中common应用程序中有Cat和Toy两个模型,Toy模型包含一个外键belongs_to指向Cat模型。
现在我们希望将Cat模型从common应用程序迁移到specific应用程序中。
解决方法如下:
首先,在common应用程序的models.py文件中,引入specific应用程序的Cat模型,并删除原先common应用程序中的Cat模型的定义。
然后,在specific应用程序的models.py文件中,定义Cat模型。
接下来,运行以下命令生成迁移文件:
./manage.py schemamigration common --auto
./manage.py schemamigration specific --auto
这样会生成两个迁移文件,一个是common应用程序的迁移文件,一个是specific应用程序的迁移文件。
在common应用程序的迁移文件中,我们需要删除common应用程序中的Cat表,并修改common应用程序中Toy模型的belongs_to外键,将其指向specific应用程序中的Cat模型。
在specific应用程序的迁移文件中,我们需要创建specific应用程序中的Cat表。
此外,为了确保迁移的顺序,我们需要添加一个依赖关系,告诉Django在应用迁移时应该先执行哪个迁移文件。
具体操作如下:
在common应用程序的迁移文件中,添加depends_on属性,并指定依赖的迁移文件。
在specific应用程序的迁移文件中,添加depends_on属性,并指定依赖的迁移文件。
depends_on属性可以确保在向前迁移时,先执行指定的依赖迁移文件,而在向后迁移时,执行的顺序与指定的依赖迁移文件相反。
最后,我们可以运行迁移命令进行数据库迁移。
希望这篇文章对大家有所帮助!