【问题标题】:Renaming a django model class-name and corresponding foreign keys with south, without loosing the data用 south 重命名 django 模型类名和相应的外键,而不会丢失数据
【发布时间】:2011-11-21 01:54:54
【问题描述】:

以下是我的模型:

class myUser_Group(models.Model):
    name = models.CharField(max_length=100)


class Channel(models.Model):
    name = models.CharField(max_length=100)
    description = models.CharField(max_length=1000)
    belongs_to_group = models.ManyToManyField(myUser_Group)

class Video(models.Model):
    video_url = models.URLField(max_length=300) 
    belongs_to_channel = models.ManyToManyField(Channel)
    description = models.CharField(max_length=1000)
    tags = TagField()

class UserProfile(models.Model):
       user = models.OneToOneField(User)

class User_History(models.Model):
    date_time = models.DateTimeField()
    user = models.ForeignKey(UserProfile, null=True, blank=True)
    videos_watched = models.ManyToManyField(Video)

我只是想从所有类名中删除下划线,以便User_History 看起来UserHistory,外键也应该更新。我尝试使用南,但在文档中找不到它。

一种方法是导出数据,卸载南,删除迁移,重命名表,然后再次导入数据。还有其他方法吗?

【问题讨论】:

  • 您想在管理员中完成这项工作吗?如果是这样stackoverflow.com/questions/7413488/… 应该会有所帮助
  • 是的,非常真实!但我仍然需要更改模型名称,以遵守 pep-8。

标签: python django mysql-management django-south


【解决方案1】:

mmcnickle 的解决方案可能有效并且看起来很合理,但我更喜欢两步过程。在第一步中,您更改表名。

在您的模型中确保您的新表名位于:

class Meta:
        db_table = new_table_name'

然后像 mmcnickle 建议的那样,创建一个自定义迁移:

python manage.py schemamigration xyz migration_name --empty

您可以在此处阅读更多相关信息: https://docs.djangoproject.com/en/dev/ref/models/options/

现在,在您的自定义迁移中,还添加行以向前和向后重命名您的表:

db.rename_table("old_table_name","new_table_name")

这足以迁移和更改表名,但如果您之前一直使用 Class Meta 自定义表名,那么您将不得不做更多的事情。因此,我通常会说,为了安全起见,在迁移文件中搜索“old_table_name”并将找到的任何条目更改为新表名。例如,如果您以前使用 Class Meta 自定义表名,您可能会看到:

'Meta': {'object_name': 'ModelNameYouWillChangeNext', 'db_table': "u'old_table_name'"},

因此,您需要将旧表名更改为新表名。

现在您可以通过以下方式进行迁移:

python manage.py migrate xyz

此时您的应用程序应该可以运行了,因为您所做的只是更改表名并告诉 Django 查找新表名。

第二步是更改您的型号名称。这实际上取决于您的应用程序,但基本上您只需将所有引用旧模型名称的代码更改为引用新模型名称的代码。如果出于组织目的在其中使用旧模型名称,您可能还需要更改一些文件名和目录名称。

完成此操作后,您的应用应该可以正常运行。至此,您的任务已基本完成,您的应用程序应该可以使用新模型名称和新表名称正常运行。使用 South 时遇到的唯一问题是下次使用它的自动检测功能创建迁移时,它会尝试删除旧表并从头开始创建一个新表,因为它检测到了您的新模型名称。要解决此问题,您需要创建另一个自定义迁移:

python manage.py schemamigration xyz tell_south_we_changed_the_model_name_for_old_model_name --empty

好消息是您在这里什么都不做,因为您已经更改了模型名称,所以 South 选择了这个。只需在向前和向后迁移中使用“pass”进行迁移:

python manage.py migrate xyz

什么都没做,South 现在意识到它是最新的。试试:

python manage.py schemamigration xyz --auto

你应该会看到它没有检测到任何变化

【讨论】:

    【解决方案2】:

    您可以只使用 South 来做到这一点。

    对于这个示例,我有一个名为 usergroups 的应用程序,其型号如下:

    class myUser_Group(models.Model):
        name = models.CharField(max_length=100)
    

    我认为它已经在 South 的迁移控制之下。

    更改模型名称:

    class MyUserGroup(models.Model):
        name = models.CharField(max_length=100)
    

    并从南方创建一个空迁移

    $ python manage.py schemamigration usergroups model_name_change --empty
    

    这将创建一个骨架迁移文件,供您指定发生的情况。如果我们编辑它,它看起来像这样(这个文件将在 app_name/migrations/ 文件夹中——在这种情况下是 usergroups/migrations/):

    import datetime
    from south.db import db
    from south.v2 import SchemaMigration
    from django.db import models
    
    class Migration(SchemaMigration):
    
        def forwards(self, orm):
            # Change the table name from the old model name to the new model name
            # ADD THIS LINE (using the correct table names)
            db.rename_table('usergroups_myuser_group', 'usergroups_myusergroup')
    
    
        def backwards(self, orm):
            # Provide a way to do the migration backwards by renaming the other way
            # ADD THIS LINE (using the correct table names)
            db.rename_table('usergroups_myusergroup', 'usergroups_myuser_group')
    
    
        models = {
            'usergroups.myusergroup': {
                'Meta': {'object_name': 'MyUserGroup'},
                'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
                'name': ('django.db.models.fields.CharField', [], {'max_length': '100'})
            }
        }
    
        complete_apps = ['usergroups']
    

    forwards 方法中,我们重命名数据库表名以匹配 django ORM 将使用新模型名查找的内容。我们撤消了 backwards 中的更改,以确保可以在需要时退回迁移。

    无需导入/导出现有数据即可运行迁移:

    $ python manage.py 迁移

    剩下的唯一步骤是更新模型中引用 myUser_Group 的外键和多对多列,并更改为引用 MyUserGroup。

    【讨论】:

      猜你喜欢
      • 2011-03-15
      • 2011-03-29
      • 2011-02-21
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2013-05-14
      • 1970-01-01
      • 2011-07-23
      相关资源
      最近更新 更多