ValueError:无法在OneToOneField关系上分配User:issue

时间:2015-04-17 13:02:23

标签: python django

我在使用OneToOneField时遇到了一个非常奇怪的问题。我是一个非常简单的模型,如

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

问题在于迁移中的方法RunPython。我编写了一个取决于0001_initial的0002_addusers迁移,代码如下:

class Migration(migrations.Migration):
    def create_users(apps, schema_editor):
        u = User.objects.create_superuser('admin', 'admin@aaa.com', 'admin')
        u.save()

        du = User.objects.create_user(username='doc01', password='doc01')
        du.save()

def create_doctors(apps, schema_editor):
    Doctor = apps.get_model('custom_user', 'Doctor')
    du = User.objects.get(username='doc01')

    d = Doctor(user=du)
    d.save()

dependencies = [
    ('custom_user', '0001_initial')
]

operations = [
    migrations.RunPython(create_users),
    migrations.RunPython(create_doctors),
]

对我来说真正奇怪的是,这个非常简单的代码在视图中工作,在shell中工作,除了迁移之外在任何地方都可以工作:)

回溯如下:

line 23, in create_doctors
d = Doctor(user=du)
...
ValueError: Cannot assign "<User: doc01>": "Doctor.user" must be a "User" instance.

非常感谢您的支持!

修改 我找到了解决方案。我只需要调用RunPython

migrations.RunPython(create_users,create_doctor)

Avinash建议的那样即使没有在课堂外移动函数。

似乎必须将后续函数作为单个RunPython调用的参数调用。

2 个答案:

答案 0 :(得分:4)

运行migrations.RunPython(create_users, create_doctor)的建议答案并不能解决您的问题,只会使其无形。

RunPython的第二个参数是在回滚期间将被调用的函数,这就是为什么它在向上迁移时不会引发任何异常的原因。你从未调用函数create_doctors

您的问题是由du不是User实例引起的。在不使用apps.get_model获取模型类时,可能会在迁移中导致此问题。您应该使用以下代码:

class Migration(migrations.Migration):
    def create_users(apps, schema_editor):
        User = apps.get_model('auth', 'User')  # Here you get the user programatically, it is a good practise in migrations
        u = User.objects.create_superuser('admin', 'admin@aaa.com', 'admin')
        u.save()

        du = User.objects.create_user(username='doc01', password='doc01')
        du.save()

    def create_doctors(apps, schema_editor):
        Doctor = apps.get_model('custom_user', 'Doctor')
        User = apps.get_model('auth', 'User')  # Here you get the user programatically, it is a good practise in migrations
        du = User.objects.get(username='doc01')

        d = Doctor(user=du)
        d.save()

    dependencies = [
        ('custom_user', '0001_initial')
    ]

    operations = [
        migrations.RunPython(create_users),
        migrations.RunPython(create_doctors),
    ]

答案 1 :(得分:2)

我认为问题出在您的迁移代码中。在Migration类之外定义方法,然后从migration的RunPython命令调用它。

在迁移文件中尝试以下代码。这将有效。

def create_users(apps, schema_editor):
    u = User.objects.create_superuser('admin', 'admin@aaa.com', 'admin')
    u.save()

    du = User.objects.create_user(username='doc01', password='doc01')
    du.save()

def create_doctors(apps, schema_editor):
    Doctor = apps.get_model('custom_user', 'Doctor')
    du = User.objects.get(username='doc01')
    # We can't import the Doctor model directly, But we can create it. Try this - 
    Doctor.objects.create(user=du)

class Migration(migrations.Migration):

    dependencies = [
        ('custom_user', '0001_initial')
    ]

    operations = [
        migrations.RunPython(create_users, create_doctors),
    ]