GenericForeignKey data migtation error: 'content_object' is an invalid keyword argument
Asked Answered
D

3

7

I want to create data migrations for a model(Comment) which has a GenericForeignKey relation. My model was made according to django documentation for contenttypes.

Models:

...
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')

Data migration:

...
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)
]

When I run ./manage.py migrate I get:

TypeError: 'content_object' is an invalid keyword argument for this function

I have to say that I have used same code as create_comment inside a view and works well.

Im using django 1.7.7. Im not using south.

Edit: I tried Shang Wang's answer.

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
) 

Is not working either:

ValueError: Cannot assign "<ContentType: nice meme>": "Comment.content_type"  must be a "ContentType" instance.
Doroteya answered 31/10, 2015 at 0:6 Comment(3)
I'm also having this same issue, and using Django 1.8.3 :/Reinareinald
Did you check the answer?Reinareinald
Im sorry. I was taking a vacation. I will look at it in a few hours. Thank you.Doroteya
R
18

As I said, I've been through this same problem and a colleague helped me with this tip:

You really need to set content_type and object_pk as +Shang Wang pointed out, but ContentType must be loaded using apps.get_model instead of directly import it.

So use this:

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

In your migration method and all should work :)

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
    )
Reinareinald answered 4/11, 2015 at 16:29 Comment(2)
Is not working that way. ContentType.objects is actually django.db.models.manager.Manager so what I did was: nice_meme_contenttype = ContentType.objects.get( app_label='comments', model='nicememe' ) model name must be lowercase. And now is working :)Doroteya
Weird @LaraChícharo ... did you load ContentType using apps.get_model? I'm glad you've solved your problem BTW :)Reinareinald
M
0

Please try this:

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)

I think the problem is that your content_object field is just a simple way for your Comment model objects to access the foreignkey quickly, like:

obj = some_comment.content_object

It's not an actual field but a combination of 2 fields, so you cannot directly assign one single NiceMeme object to it.

Edit:

Sounds like you are using South, there's an issue described here. The solution is answered in another SO thread. Sounds like the solution is to freeze any model that your migration is related:

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

You might need to freeze more apps:

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

I never encountered this problem before, so please read original post for more details, hope this helps.

Melisa answered 31/10, 2015 at 0:56 Comment(3)
Thank you for your answer. Unfortunately, I got this: ValueError: Cannot assign "<ContentType: nice meme>": "Comment.content_type" must be a "ContentType" instance.Doroteya
I updated my answer, I don't have enough knowledge to deal with this, but try the thread I found see if it helps.Melisa
Im not using south, Im using django 1.7.7. Sorry for telling you until now. Thanks for your help.Doroteya
C
0

I had the same problem, the solution is to get ContentType object with the model name in lowercase:

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

For this question:

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
    )
Clydeclydebank answered 20/10, 2017 at 10:43 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.