首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >问答首页 >姜戈ReverseSingleRelatedObjectDescriptor.__set__ ValueError

姜戈ReverseSingleRelatedObjectDescriptor.__set__ ValueError
EN

Stack Overflow用户
提问于 2015-03-18 20:40:23
回答 2查看 841关注 0票数 2

我正在创建一个自定义数据迁移,以便根据跨两个不同模型的现有条目自动在数据库中创建GenericRelation条目。

示例models.py:

代码语言:javascript
复制
...
class Place
   content_type = models.ForeignKey(ContentType)
   object_id = models.PositiveIntegerField()
   content_object = generic.GenericForeignKey('content_type', 'object_id')


class Restaurant
   name = models.CharField(max_length=60)
   location = models.CharField(max_length=60)


class House
   location = models.CharField(max_length=60)

示例0011_place_data.py:

代码语言:javascript
复制
# -*- coding: utf-8 -*-
from django.contrib.contenttypes.models import ContentType
from django.db import models, migrations

def forwards_func(apps, schema_editor):
    Restaurant = apps.get_model("simpleapp", "Restaurant")
    House = apps.get_model("simpleapp", "House")
    Place = apps.get_model("simpleapp", "Place")

    db_alias = schema_editor.connection.alias

    content_type = ContentType.objects.using(db_alias).get(
        app_label="simpleapp",
        model="restaurant"
    )

    for restaurant in Restaurant.objects.using(db_alias).all():
        Place.objects.using(db_alias).create(
            content_type=content_type,
            object_id=restaurant.id)

    content_type = ContentType.objects.using(db_alias).get(
        app_label="simpleapp",
        model="house"
    )
    for house in House.objects.using(db_alias).all():
        Place.objects.using(db_alias).create(
            content_type=content_type,
            object_id=house.id)


class Migration(migrations.Migration):

    dependencies = [
        ('simpleapp', '0010_place')
    ]

    operations = [
        migrations.RunPython(
            forwards_func,
        ),
    ]

当我运行这个(Django 1.7.4)时,我得到

代码语言:javascript
复制
Operations to perform:
  Apply all migrations: simpleapp, admin, sessions, auth, contenttypes
Synchronizing apps without migrations:
  Creating tables...
  Installing custom SQL...
  Installing indexes...
Running migrations:
  Applying projects.0011_place_data...passing
Traceback (most recent call last):
  File "manage.py", line 10, in <module>
    execute_from_command_line(sys.argv)
  File ".../lib/python3.4/site-packages/django/core/management/__init__.py", line 385, in execute_from_command_line
utility.execute()
  File ".../lib/python3.4/site-packages/django/core/management/__init__.py", line 377, in execute
self.fetch_command(subcommand).run_from_argv(self.argv)
  File ".../lib/python3.4/site-packages/django/core/management/base.py", line 288, in run_from_argv
self.execute(*args, **options.__dict__)
  File ".../lib/python3.4/site-packages/django/core/management/base.py", line 338, in execute
output = self.handle(*args, **options)
  File ".../lib/python3.4/site-packages/django/core/management/commands/migrate.py", line 161, in handle
executor.migrate(targets, plan, fake=options.get("fake", False))
  File ".../lib/python3.4/site-packages/django/db/migrations/executor.py", line 68, in migrate
self.apply_migration(migration, fake=fake)
  File ".../lib/python3.4/site-packages/django/db/migrations/executor.py", line 102, in apply_migration
migration.apply(project_state, schema_editor)
  File ".../lib/python3.4/site-packages/django/db/migrations/migration.py", line 108, in apply
operation.database_forwards(self.app_label, schema_editor, project_state, new_state)
  File ".../lib/python3.4/site-packages/django/db/migrations/operations/special.py", line 117, in database_forwards
self.code(from_state.render(), schema_editor)
  File ".../simpleapp/migrations/0011_place_data.py", line 19, in forwards_func
object_id=restaurant.id)
  File ".../lib/python3.4/site-packages/django/db/models/query.py", line 370, in create
obj = self.model(**kwargs)
  File ".../lib/python3.4/site-packages/django/db/models/base.py", line 440, in __init__
setattr(self, field.name, rel_obj)
  File ".../lib/python3.4/site-packages/django/db/models/fields/related.py", line 598, in __set__
self.field.rel.to._meta.object_name,
ValueError: Cannot assign "<ContentType: restaurant>": "Place.content_type" must be a "ContentType" instance.

如果我注释掉了引发Django模块(django.db.models.fields.related.ReverseSingleRelatedObjectDescriptor.set)中值错误的那一节,它就会像预期的那样工作:

代码语言:javascript
复制
...

    elif value is not None and not isinstance(value, self.field.rel.to):
        print('skipping')
        #raise ValueError(
        #    'Cannot assign "%r": "%s.%s" must be a "%s" instance.' % (
        #        value,
        #        instance._meta.object_name,
        #        self.field.name,
        #        self.field.rel.to._meta.object_name,
        #    )
        #)

...

首先应该提出这一例外吗?这是Django的一个bug,还是我做错了?

EN

回答 2

Stack Overflow用户

发布于 2015-03-19 17:18:36

编辑

下面的解决方案实际上不起作用;它只是没有运行forwards_func,所以没有错误。欢迎新的解决办法:

我能够使用迁移信号解决这个问题。

这还解决了这些类型迁移(引用ContentType表的数据迁移)带来的其他一些问题。

我的理解是,从本质上讲,问题在于由于性能原因,直到迁移结束时才会创建ContentType表。这意味着我实际上不会检索与关系模块正在检查的相同类型的ContentType对象。

解决方案是将这种类型的数据迁移作为回调运行:

代码语言:javascript
复制
# -*- coding: utf-8 -*-
from django.db.models.signals import post_migrate
from django.contrib.contenttypes.models import ContentType
from django.db import models, migrations

def forwards_func(apps, schema_editor):
    Restaurant = apps.get_model("simpleapp", "Restaurant")
    House = apps.get_model("simpleapp", "House")
    Place = apps.get_model("simpleapp", "Place")

    db_alias = schema_editor.connection.alias

    def add_stuffs(*args, **kwargs)
        content_type = ContentType.objects.using(db_alias).get(
            app_label="simpleapp",
            model="restaurant"
        )

        for restaurant in Restaurant.objects.using(db_alias).all():
            Place.objects.using(db_alias).create(
                content_type=content_type,
                object_id=restaurant.id)

        content_type = ContentType.objects.using(db_alias).get(
            app_label="simpleapp",
            model="house"
        )
        for house in House.objects.using(db_alias).all():
            Place.objects.using(db_alias).create(
               content_type=content_type,
               object_id=house.id)

    post_migrate.connect(add_stuffs)


class Migration(migrations.Migration):

    dependencies = [
        ('simpleapp', '0010_place')
    ]

    operations = [
        migrations.RunPython(
            forwards_func,
        ),
    ]
票数 1
EN

Stack Overflow用户

发布于 2016-07-26 18:39:49

看起来它和这个Django 错误/修复有点关系

在迁移过程中,当试图重新分配权限给用户组时,我也犯了类似的错误。要修复它,我必须手动发出post_migrate信号,如这里所描述的那样。

下面是我的迁移代码示例:

代码语言:javascript
复制
# -*- coding: utf-8 -*-
from __future__ import unicode_literals

from django.db import migrations
from django.core.management.sql import emit_post_migrate_signal


def trigger_post_migrate(db_alias):
    try:
        # Django 1.9
        emit_post_migrate_signal(2, False, db_alias)
    except TypeError:
        # Django < 1.9
        try:
            # Django 1.8
            emit_post_migrate_signal(2, False, 'default', db_alias)
        except TypeError:
            # Django < 1.8
            emit_post_migrate_signal([], 2, False, 'default', db_alias)


def up(apps, schema_editor):
    # trigger post migrate to make sure all permissions and contenttypes are in place
    trigger_post_migrate(schema_editor.connection.alias)

    # migration code here...


class Migration(migrations.Migration):
    dependencies = [
        ('accounts', '0008_auto_20160712_0608'),
    ]

    operations = [
        migrations.RunPython(up),
    ]
票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/29132210

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档