通用外键数据迁移错误: 'content_object'是无效的关键字参数。

7
我希望为一个具有GenericForeignKey关系的模型(Comment)创建数据迁移。我的模型是根据contenttypes的Django文档制作的。django documentation

模型:

...
class NiceMeme(models.Model):
    """
        Example model.
    """

    name = models.CharField(max_length=140)
    image = models.ImageField(upload_to=get_path_to_store_nice_meme_images)


class Comment(models.Model):
    """
        Model to add comments to any other (non abstract) model.
    """
    ...
    user = models.ForeignKey(ExtendedUser)
    content = models.CharField(max_length=140)
    content_type = models.ForeignKey(ContentType)
    object_pk = models.PositiveIntegerField()
    content_object = GenericForeignKey('content_type', 'object_pk')

数据迁移:


...
def create_comment(apps, schema_editor):
    ...
    nice_meme = NiceMeme.objects.create(name='Nice nice meme')
    Comment.objects.create(
        user=user,
        content='Gott ist tot',
        poster_username='Friedrich',
        content_object=nice_meme
    )

...
operations = [
    migrations.RunPython(create_comment)
]

当我运行./manage.py migrate时,出现以下错误:TypeError: 'content_object' is an invalid keyword argument for this function。需要说明的是,我已经在视图中使用了与create_comment相同的代码,并且运行良好。我的django版本为1.7.7,我没有使用south。 编辑:我尝试了Shang Wang的答案。
Comment.objects.create(
    user=user,
    content='Gott ist tot', 
    poster_username='Friedrich',
    content_type=ContentType.objects.get_for_model(nice_meme),
    object_pk=nice_meme.id
) 

也没有起作用:

ValueError: Cannot assign "<ContentType: nice meme>": "Comment.content_type"  must be a "ContentType" instance.

我也遇到了同样的问题,使用的是Django 1.8.3 :/ - Rafael Verger
你检查了答案吗? - Rafael Verger
对不起,我正在度假。几个小时后我会看一下它。谢谢。 - Laraconda
3个回答

17

正如我所说的,我经历过同样的问题,一个同事帮了我一下:

你确实需要像+Shang Wang指出的那样设置content_typeobject_pk,但是ContentType必须使用apps.get_model来加载,而不是直接导入。

因此,在您的迁移方法中使用以下代码:

ContentType = apps.get_model('contenttypes', 'ContentType')

这样就可���了 :)

def create_comment(apps, schema_editor):
    ...
    ContentType = apps.get_model('contenttypes', 'ContentType')
    nice_meme = NiceMeme.objects.create(name='Nice nice meme')
    Comment.objects.create(
        user=user,
        content='Gott ist tot',
        poster_username='Friedrich',
        content_type=ContentType.objects.get_for_model(nice_meme),
        object_pk=nice_meme.id
    )

不是这样工作的。ContentType.objects 实际上是 django.db.models.manager.Manager,所以我做的是:nice_meme_contenttype = ContentType.objects.get( app_label='comments', model='nicememe' ) 模型名称必须小写。现在可以工作了 :) - Laraconda
奇怪的@LaraChícharo...你是用apps.get_model加载ContentType吗?顺便说一下,我很高兴你解决了问题 :) - Rafael Verger

0
请尝试这个:
from django.contrib.contenttypes.models import ContentType

nice_meme = NiceMeme.objects.create(name='Nice nice meme')
Comment.objects.create(user=user,
                       content='Gott ist tot', 
                       poster_username='Friedrich',
                       content_type=ContentType.objects.get_for_model(nice_meme),
                       object_pk=nice_meme.id)

我认为问题在于你的content_object字段只是让你的Comment模型对象快速访问外键的简单方法,例如:

obj = some_comment.content_object

它不是一个实际的字段,而是两个字段的组合,所以您不能直接将单个NiceMeme对象分配给它。

编辑:

听起来你正在使用South,在这里描述了一个问题here。解决方案在另一个SO thread中得到了回答。听起来解决方案是冻结与您的迁移相关的任何模型:

python manage.py schemamigration --auto yourapp --freeze contenttypes

你可能需要冻结更多的应用程序:

python manage.py schemamigration --auto yourapp --freeze contenttypes --freeze someotherapp ...

我以前从未遇到过这个问题,所以请阅读原帖获取更多细节,希望能对你有所帮助。


谢谢您的回答。不幸的是,我收到了以下错误提示:ValueError: 无法分配 "<ContentType: nice meme>" :"Comment.content_type" 必须是 "ContentType" 实例。 - Laraconda
我更新了我的回答,我没有足够的知识来处理这个问题,但是尝试一下我找到的线程,看看是否有帮助。 - Shang Wang
我没有使用South,我正在使用Django 1.7.7。很抱歉直到现在才告诉你。感谢您的帮助。 - Laraconda

0

我曾经遇到过同样的问题,解决方法是使用小写的模型名称获取ContentType对象:

content=ContentType.objects.get(app_label='appname', model='modelname')

针对这个问题:

def create_comment(apps, schema_editor):
    ContentType = apps.get_model('contenttypes', 'ContentType')    
    nice_meme = NiceMeme.objects.create(name='Nice nice meme')

    Comment.objects.create(
        user=user,
        content=ContentType.objects.get(app_label='appname', model='nicememe')
        poster_username='Friedrich',
        content_object=nice_meme
    )

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接