首页
学习
活动
专区
工具
TVP
发布
社区首页 >问答首页 >如何将模型从django应用程序迁移到新的应用程序?

如何将模型从django应用程序迁移到新的应用程序?
EN

Stack Overflow用户
提问于 2009-08-11 01:57:23
回答 4查看 37.8K关注 0票数 131

我有一个django应用程序,里面有四个模型。我现在意识到,这些模型中的一个应该放在单独的应用程序中。我确实为迁移安装了south,但我不认为这是它可以自动处理的事情。如何将旧应用程序中的一个模型迁移到新应用程序中?

此外,请记住,我需要这是一个可重复的过程,以便我可以迁移生产系统等。

EN

回答 4

Stack Overflow用户

发布于 2009-08-11 06:40:17

模型与应用程序的耦合不是很紧密,所以移动起来相当简单。Django在数据库表的名称中使用应用程序名称,所以如果你想移动你的应用程序,你可以通过SQL ALTER TABLE语句重命名数据库表,或者--更简单--只需在模型的Meta类中使用db_table parameter来引用旧名称。

如果到目前为止,您已经在代码中的任何地方使用了ContentTypes或泛型关系,那么您可能希望重命名指向正在移动的模型的contenttype的app_label,以便保留现有的关系。

当然,如果您根本没有要保留的数据,最简单的做法是完全删除数据库表,然后再次运行./manage.py syncdb

票数 13
EN

Stack Overflow用户

发布于 2014-08-01 14:32:02

这个过程我现在已经决定了,因为我已经回到这里几次了,并决定将其正式化。

这最初是在Potr Czachur's answerMatt Briançon's answer上构建的,使用South 0.8.4

步骤1.发现子外键关系

代码语言:javascript
复制
# Caution: This finds OneToOneField and ForeignKey.
# I don't know if this finds all the ways of specifying ManyToManyField.
# Hopefully Django or South throw errors if you have a situation like that.
>>> Cat._meta.get_all_related_objects()
[<RelatedObject: common:toy related to cat>,
 <RelatedObject: identity:microchip related to cat>]

所以在这个扩展的例子中,我们发现了另一个相关的模型,比如:

代码语言:javascript
复制
# Inside the "identity" app...
class Microchip(models.Model):

    # In reality we'd probably want a ForeignKey, but to show the OneToOneField
    identifies = models.OneToOneField(Cat)

    ...

步骤2.创建迁移

代码语言:javascript
复制
# Create the "new"-ly renamed model
# Yes I'm changing the model name in my refactoring too.
python manage.py schemamigration specific create_kittycat --auto

# Drop the old model
python manage.py schemamigration common drop_cat --auto

# Update downstream apps, so South thinks their ForeignKey(s) are correct.
# Can skip models like Toy if the app is already covered
python manage.py schemamigration identity update_microchip_fk --auto

步骤3.源代码控制:到目前为止提交更改。

如果你遇到合并冲突,比如团队成员在更新的应用程序上编写迁移,这将使其更具可重复性。

步骤4.在迁移之间添加依赖关系。

基本上,create_kittycat依赖于所有内容的当前状态,然后所有内容都依赖于create_kittycat

代码语言:javascript
复制
# create_kittycat
class Migration(SchemaMigration):

    depends_on = (
        # Original model location
        ('common', 'the_one_before_drop_cat'),

        # Foreign keys to models not in original location
        ('identity', 'the_one_before_update_microchip_fk'),
    )
    ...


# drop_cat
class Migration(SchemaMigration):

    depends_on = (
        ('specific', 'create_kittycat'),
    )
    ...


# update_microchip_fk
class Migration(SchemaMigration):

    depends_on = (
        ('specific', 'create_kittycat'),
    )
    ...

步骤5.我们想要进行的表重命名更改。

代码语言:javascript
复制
# create_kittycat
class Migration(SchemaMigration):

    ...

    # Hopefully for create_kittycat you only need to change the following
    # 4 strings to go forward cleanly... backwards will need a bit more work.
    old_app = 'common'
    old_model = 'cat'
    new_app = 'specific'
    new_model = 'kittycat'

    # You may also wish to update the ContentType.name,
    # personally, I don't know what its for and
    # haven't seen any side effects from skipping it.

    def forwards(self, orm):

        db.rename_table(
            '%s_%s' % (self.old_app, self.old_model),
            '%s_%s' % (self.new_app, self.new_model),
        )

        if not db.dry_run:
            # For permissions, GenericForeignKeys, etc to work properly after migrating.
            orm['contenttypes.contenttype'].objects.filter(
                app_label=self.old_app,
                model=self.old_model,
            ).update(
                app_label=self.new_app,
                model=self.new_model,
            )

        # Going forwards, should be no problem just updating child foreign keys
        # with the --auto in the other new South migrations

    def backwards(self, orm):

        db.rename_table(
            '%s_%s' % (self.new_app, self.new_model),
            '%s_%s' % (self.old_app, self.old_model),
        )

        if not db.dry_run:
            # For permissions, GenericForeignKeys, etc to work properly after migrating.
            orm['contenttypes.contenttype'].objects.filter(
                app_label=self.new_app,
                model=self.new_model,
            ).update(
                app_label=self.old_app,
                model=self.old_model,
            )

        # Going backwards, you probably should copy the ForeignKey
        # db.alter_column() changes from the other new migrations in here
        # so they run in the correct order.
        #
        # Test it! See Step 6 for more details if you need to go backwards.
        db.alter_column('common_toy', 'belongs_to_id', self.gf('django.db.models.fields.related.ForeignKey')(to=orm['common.Cat']))
        db.alter_column('identity_microchip', 'identifies_id', self.gf('django.db.models.fields.related.OneToOneField')(to=orm['common.Cat']))


# drop_cat
class Migration(SchemaMigration):

    ...

    def forwards(self, orm):
        # Remove the db.delete_table(), if you don't at Step 7 you'll likely get
        # "django.db.utils.ProgrammingError: table "common_cat" does not exist"

        # Leave existing db.alter_column() statements here
        db.alter_column('common_toy', 'belongs_to_id', self.gf('django.db.models.fields.related.ForeignKey')(to=orm['specific.KittyCat']))

    def backwards(self, orm):
        # Copy/paste the auto-generated db.alter_column()
        # into the create_kittycat migration if you need backwards to work.
        pass


# update_microchip_fk
class Migration(SchemaMigration):

    ...

    def forwards(self, orm):
        # Leave existing db.alter_column() statements here
        db.alter_column('identity_microchip', 'identifies_id', self.gf('django.db.models.fields.related.OneToOneField')(to=orm['specific.KittyCat']))

    def backwards(self, orm):
        # Copy/paste the auto-generated db.alter_column()
        # into the create_kittycat migration if you need backwards to work.
        pass

第6步。仅当您需要使用backwards()来工作并让KeyError向后运行时。

代码语言:javascript
复制
# the_one_before_create_kittycat
class Migration(SchemaMigration):

    # You many also need to add more models to South's FakeORM if you run into
    # more KeyErrors, the trade-off chosen was to make going forward as easy as
    # possible, as that's what you'll probably want to do once in QA and once in
    # production, rather than running the following many times:
    #
    # python manage.py migrate specific <the_one_before_create_kittycat>

    models = {
        ...
        # Copied from 'identity' app, 'update_microchip_fk' migration
        u'identity.microchip': {
            'Meta': {'object_name': 'Microchip'},
            u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
            'name': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '80'}),
            'identifies': ('django.db.models.fields.related.OneToOneField', [], {to=orm['specific.KittyCat']})
        },
        ...
    }

第7步.测试它-对我有效的可能不足以满足您的实际情况:)

代码语言:javascript
复制
python manage.py migrate

# If you need backwards to work
python manage.py migrate specific <the_one_before_create_kittycat>
票数 4
EN

Stack Overflow用户

发布于 2013-12-13 18:07:16

因此,在South 0.8.1和Django 1.5.1上,使用来自上述@Potr的原始响应不适用于我。我在下面发布了对我有用的东西,希望能对其他人有所帮助。

代码语言:javascript
复制
from south.db import db
from south.v2 import SchemaMigration
from django.db import models

class Migration(SchemaMigration):

    def forwards(self, orm):
        db.rename_table('common_cat', 'specific_cat') 

        if not db.dry_run:
             db.execute(
                "update django_content_type set app_label = 'specific' where "
                " app_label = 'common' and model = 'cat';")

    def backwards(self, orm):
        db.rename_table('specific_cat', 'common_cat')
            db.execute(
                "update django_content_type set app_label = 'common' where "
                " app_label = 'specific' and model = 'cat';")
票数 3
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/1258130

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档