我不想毁掉我网站上的所有用户.但是我想利用Django 1.5的自定义可插拔用户模型.这是我的新用户模型:

class SiteUser(AbstractUser):
    site = models.ForeignKey(Site, null=True)

在新的安装中,我的新模型可以正常工作(我有其他代码,以及这样做的一个很好的理由——所有这些都与此无关).但如果我把这个放在我的直播网站和syncdb&如果迁移,我将失go 所有用户,或者至少他们将位于与为新模型创建的新表不同的孤立表中.

我对South很熟悉,但是根据this post个数据迁移和我自己的一些试验,它的数据迁移目前似乎不适合这个特定的migrations.因此,我正在寻找某种方法,使South既可以用于此迁移,也可以用于某些非South迁移(原始SQL、dumpdata/loaddata或其他),这样我就可以在我的每台服务器(Postgres 9.2)上运行这些方法,以便在创建了新表之后迁移用户,而旧auth.User表仍在数据库中.

推荐答案

南方完全有能力为您完成这次迁移,但您需要聪明一点,分阶段进行.下面是分步指南:(本指南假定您有AbstractUser个子类,而不是AbstractBaseUser个子类)

  1. 在进行切换之前,请确保在应用程序中启用了SOUTH支持 它包含您的自定义用户模型(出于指南的目的,我们将其命名为accounts和模型User). 在这一点上,您应该有一个自定义的用户模型not yet.

    $ ./manage.py schemamigration accounts --initial
    Creating migrations directory at 'accounts/migrations'...
    Creating __init__.py in 'accounts/migrations'...
    Created 0001_initial.py.
    
    $ ./manage.py migrate accounts [--fake if you've already syncdb'd this app]
     Running migrations for accounts:
     - Migrating forwards to 0001_initial.
     > accounts:0001_initial
     - Loading initial data for accounts.
    
  2. 在accounts应用程序中创建一个新的空白用户migrations.

    $ ./manage.py schemamigration accounts --empty switch_to_custom_user
    Created 0002_switch_to_custom_user.py.
    
  3. accounts应用程序中创建自定义User型号,但确保将其定义为:

    class SiteUser(AbstractUser): pass
    
  4. 使用以下代码填充空白migrations.

    # encoding: utf-8
    from south.db import db
    from south.v2 import SchemaMigration
    
    class Migration(SchemaMigration):
    
        def forwards(self, orm):
            # Fill in the destination name with the table name of your model
            db.rename_table('auth_user', 'accounts_user')
            db.rename_table('auth_user_groups', 'accounts_user_groups')
            db.rename_table('auth_user_user_permissions', 'accounts_user_user_permissions')
    
        def backwards(self, orm):
            db.rename_table('accounts_user', 'auth_user')
            db.rename_table('accounts_user_groups', 'auth_user_groups')
            db.rename_table('accounts_user_user_permissions', 'auth_user_user_permissions')
    
        models = { ....... } # Leave this alone
    
  5. 运行迁移

    $ ./manage.py migrate accounts
     - Migrating forwards to 0002_switch_to_custom_user.
     > accounts:0002_switch_to_custom_user
     - Loading initial data for accounts.
    
  6. 现在对您的用户模型进行任何更改.

    # settings.py
    AUTH_USER_MODEL = 'accounts.User'
    
    # accounts/models.py
    class SiteUser(AbstractUser):
        site = models.ForeignKey(Site, null=True)
    
  7. 为此更改创建并运行迁移

    $ ./manage.py schemamigration accounts --auto
     + Added field site on accounts.User
    Created 0003_auto__add_field_user_site.py.
    
    $ ./manage.py migrate accounts
     - Migrating forwards to 0003_auto__add_field_user_site.
     > accounts:0003_auto__add_field_user_site
     - Loading initial data for accounts.
    

老实说,如果你已经对你的设置有了很好的了解,并且已经使用了south,那么它应该很简单,只需将以下迁移添加到你的accounts模块中即可.

# encoding: utf-8
from south.db import db
from south.v2 import SchemaMigration
from django.db import models

class Migration(SchemaMigration):

    def forwards(self, orm):
        # Fill in the destination name with the table name of your model
        db.rename_table('auth_user', 'accounts_user')
        db.rename_table('auth_user_groups', 'accounts_user_groups')
        db.rename_table('auth_user_permissions', 'accounts_user_permissions')
        # == YOUR CUSTOM COLUMNS ==
        db.add_column('accounts_user', 'site_id',
            models.ForeignKey(orm['sites.Site'], null=True, blank=False)))

    def backwards(self, orm):
        db.rename_table('accounts_user', 'auth_user')
        db.rename_table('accounts_user_groups', 'auth_user_groups')
        db.rename_table('accounts_user_user_permissions', 'auth_user_user_permissions')
        # == YOUR CUSTOM COLUMNS ==
        db.remove_column('accounts_user', 'site_id')

    models = { ....... } # Leave this alone

2013年2月5日编辑:增加auth_user_group表的重命名.由于数据库约束,FKS将自动更新以指向正确的表,但M2M字段的表名是从2个端表的名称生成的,需要以这种方式手动更新.

编辑2:感谢@Tuttle&;@Pix0r的更正.

Django相关问答推荐

Django逆转ForeignKey返回无

Django中有修改字段值的挂钩吗?

为什么Docker compose没有这样的文件或目录?

在生产中添加整型主键

Django没有显示变量

在生成的表单元素处出现多值DictKeyError

有谁知道是否可以将您的 Django Heroku 应用程序放到 App Store/Google Play 上?

如何让 Django 在模板更改时重新启动运行服务器?

Django - 将 HTML 输出转换为变量

django.core.exceptions.ImproperlyConfigured:请求设置 USE_I18N,但未配置设置

django:manytomanyfield 和 through 如何出现在 admin 中?

Python 社区里的小马是怎么回事?

如何从 Django 的 TabularInline 管理视图中省略对象名称?

如何查询名称包含python列表中任何单词的模型?

登录后django重定向不起作用next不发布?

如何获取经过身份验证的用户列表?

为什么我的 Django 单元测试不知道安装了 MessageMiddleware?

运行单元测试时禁用 Django South?

XlsxWriter 对象另存为 http 响应以在 Django 中创建下载

django.urls.path中name参数的作用是什么?