看似good advice之后,我通过迁移将auth.User
重命名为app.User
,从Django的内置auth_user
迁移到我自己的app_user
。到目前为止一切顺利,这很好。当我设置一台新机器时会出现问题。
在settings.py
AUTH_USER_MODEL = 'app.User'
我syncdb
。因此,当我运行auth_user
时,未创建migrate
表,因此当我AUTH_USER_MODEL
时,该迁移失败。
我发现的唯一方法是修改auth.User
以指向syncdb
,运行AUTH_USER_MODEL
并迁移直至重命名迁移,然后更改{{1}}返回,然后运行其余的迁移。
有解决这个问题的方法吗?
答案 0 :(得分:3)
根据您提到的问题,我首先尝试的方法是修改执行表重命名的迁移,以检查是否应该执行重命名。不幸的是,南does not readily cooperate有这种检查。如果迁移失败,大多数更高级别的操作都会完全中止迁移。但是,您可以使用db.execute
,如果失败,将引发异常。类似的东西:
from django.db.utils import ProgrammingError
from south.db import db
exists = False
db.start_transaction()
try:
# Will fail if the destination table does not exist.
# Any typo here will yield incorrect results. Be careful.
db.execute("select count(*) from auth_user")
# If we get here, the table exists
exists = True
except ProgrammingError:
pass
# Always end the transaction we started, rollback or commit shouldn't matter.
db.rollback_transaction()
if exists:
db.rename_table...
else:
# The table does not exist, create new one.
db.create_table...
我的测试表明,总是可以捕获South的数据库调用引发的错误。 然而,South在SQL错误后不会清理。 (这是我在本答案的第一个版本中最初错过的。)因此,即使捕获到异常,将启动的 next SQL操作也会发现连接处于错误状态。换句话说,失败操作之后发生的操作将因前一操作失败而失败。这是db.start_transaction()
和db.rollback_transaction()
来电的原因。即使出现SQL错误,这也会使操作干净利落。
答案 1 :(得分:1)
我也试图像你一样遵循相同的指示,但我选择以另一种方式修复它。我创建了我的模型(称为UserProfile),如下所示:
class UserProfile(AbstractUser):
# Fields
...
class Meta:
swappable = 'AUTH_USER_MODEL'
db_table = 'auth_user'
这样,运行syncdb
将不再导致问题,因为您的表名称正确。但是,我不记得我在做这个时所采取的所有步骤,因此可能需要更多设置。
答案 2 :(得分:1)
根据这里提出的其他答案的想法,这是一个有效的解决方案:
def forwards(self, orm):
if 'auth_user' not in db.execute('SHOW TABLES'):
db.create_table('app_user', (
(u'id', self.gf('django.db.models.fields.AutoField')(primary_key=True)),
('password', self.gf('django.db.models.fields.CharField')(max_length=128)),
('last_login', self.gf('django.db.models.fields.DateTimeField')(default=datetime.datetime.now)),
('is_superuser', self.gf('django.db.models.fields.BooleanField')(default=False)),
('username', self.gf('django.db.models.fields.CharField')(unique=True, max_length=30)),
('first_name', self.gf('django.db.models.fields.CharField')(max_length=30, blank=True)),
('last_name', self.gf('django.db.models.fields.CharField')(max_length=30, blank=True)),
('email', self.gf('django.db.models.fields.EmailField')(max_length=75, blank=True)),
('is_staff', self.gf('django.db.models.fields.BooleanField')(default=False)),
('is_active', self.gf('django.db.models.fields.BooleanField')(default=True)),
('date_joined', self.gf('django.db.models.fields.DateTimeField')(default=datetime.datetime.now)),
))
db.send_create_signal(app', ['User'])
else:
db.rename_table('auth_user', 'app_user')