我有一个现有的django-cms ver。 3.1.3项目我希望用django-custom-user中找到的用户模型替换默认的django用户模型(将电子邮件作为我的用户的用户名)。我已将custom_user
应用添加到INSTALLED_APPS
并设置AUTH_USER_MODEL = 'custom_user.EmailUser'
。最后,我应用了迁移。
我的自定义模型中的所有内容似乎都运行良好,但django-cms模型引用了auth_user
表(GlobalPagePermission
,PagePermission,
PageUser
和{ {1}})未更新为具有对新自定义用户表的外键引用。
django-cms documentation表示通常建议在项目开始时添加自定义用户模型,但在这里,我是在项目中间,并且非常希望避免删除我的cms模型(带数据)使其有效。
如果我在项目的开头,并且在迁移django-cms模型之前添加了自定义用户模型,那么django-cms模型是否会实际引用自定义用户模型表而不是默认模型表?
我有没有办法为django-cms模型进行迁移,所以他们使用新的自定义用户模型而不是默认用户模型?
我试图实现yakky建议的内容:
UserSettings
它失败,from __future__ import unicode_literals
from django.conf import settings
from django.db import models, migrations
import django.db.models.deletion
from django.utils.translation import ugettext_lazy as _
def up(apps, schema_editor):
PageUser = apps.get_model("cms", "PageUser")
db_alias = schema_editor.connection.alias
for pu in PageUser.objects.all():
pu['emailuser_ptr_id'] = pu['user_ptr_id']
pu.save()
def down(apps, schema_editor):
PageUser = apps.get_model("cms", "PageUser")
db_alias = schema_editor.connection.alias
for pu in PageUser.objects.all():
pu['user_ptr_id'] = pu['emailuser_ptr_id']
pu.save()
class Migration(migrations.Migration):
dependencies = [
migrations.swappable_dependency(settings.AUTH_USER_MODEL),
(‘myapp’, ‘previous-migration’),
]
operations = [
migrations.RenameField(
model_name='PageUser',
old_name='user_ptr_id',
new_name='user_ptr_id_old',
),
migrations.AddField(
model_name='PageUser',
name='emailuser_ptr_id',
field=models.ForeignKey(null=True, to=settings.AUTH_USER_MODEL, verbose_name=_('user'), blank=True),
preserve_default=True,
),
migrations.RunPython(up, down),
migrations.RemoveField(
model_name='PageUser',
name='user_ptr_id_old',
),
]
建议它在我的自定义应用中查找KeyError: ('myapp', u'pageuser')
模型,而不是在cms应用中。如何将这些迁移应用于cms模型?
答案 0 :(得分:3)
据说替换Django User模型在项目生命周期中是不可取的(参见https://docs.djangoproject.com/en/1.9/topics/auth/customizing/#substituting-a-custom-user-model),因为Django在创建关系后没有提供任何修改关系的方法,以替换自定义用户模型,您可以编写自定义迁移,更改django CMS模型中的外键,以指向新用户模型并为其创建一个新的。
类似的东西:
...
migrations.RenameField(
model_name='globalpagepermission',
old_name='user',
new_name='user_old',
),
migrations.AddField(
model_name='globalpagepermission',
name='user',
field=models.ForeignKey(null=True, to=settings.AUTH_USER_MODEL, verbose_name=_('user'), blank=True),
preserve_default=True,
),
migrations.RunPython(copy_data),
migrations.RemoveField(
model_name='globalpagepermission',
name='user_old',
),
...
对任何相关模型/字段重复。
copy_data
方法会将外键的值从user_old
复制到user
代码完全未经测试,但总体思路应该有效。
或者,您可以编写RunSQL迁移以获得相同的结果。
具有相同主键的用户也必须存在,才能使新模型正常工作。
答案 1 :(得分:1)
感谢https://code.djangoproject.com/ticket/25313我设法让它发挥作用。这就是我所做的:
备份我的数据库!
创建了一个新的应用程序email_username来保存我的用户模型(按照链接中的建议命名为User)。一个新的应用程序是必要的,因为我的主应用程序(myapp)依赖于django-cms,如果我将我的新用户模型放在myapp中,django-cms将依赖于我的应用程序 - 这将创建一个循环引用。
class User(AbstractEmailUser):
# Needed to add username, first_name and last_name here, because cms.PageUser model depends on these fields
username = models.CharField(max_length=100, verbose_name=_('username'))
first_name = models.CharField(max_length=100, verbose_name=_('first_name'))
last_name = models.CharField(max_length=100, verbose_name=_('last_name'))
class Meta:
db_table = 'auth_user' # the model will use the existing auth_user table (at first)
在AUTH_USER_MODEL = ‘email_username.User’
settings.py
django_migrations
表manage.py makemigrations
并得到无法解析[]的基础可以 如果您从具有迁移的应用程序继承模型(例如, contrib.auth)在没有迁移的应用程序中;看到 https://docs.djangoproject.com/en/1.8/topics/migrations/#dependencies 更多
...所以我从cms
移除了settings.py
应用,再次运行了makemigrations
,现在已经成功,然后重新添加并再次运行makemigrations
。
manage.py migrate --fake
,但得到了无法解析[ModelState:'djangocms_file.File',ModelState:'djangocms_video.Video',ModelState:'djangocms_link.Link',ModelState:'djangocms_googlemap.GoogleMap',ModelState:'djangocms_picture.Picture',ModelState: 'djangocms_teaser.Teaser']
...所以我也从settings.py
删除了这些应用,运行了migrate --fake
,重新添加了应用,再次migrate --fake
。
db_table
设置,运行makemigrations
后跟migrate
(不假冒!)现在一切似乎都井井有条。之前引用标准auth_user表的所有外键现在都引用了我的新用户模型的表。由于db_table技巧,现有用户甚至已被转移。