GenericForeignKey, ContentType and DjangoRestFramework
A

1

7

I am working on an discussion app in Django, that has Threads, Posts, Replies and Votes. Votes uses Generic Foreign Keys and Content Types to ensure a user can only vote once on a specific Thread/Post/Reply.

Vote model looks like this:

VOTE_TYPE = (
    (-1, 'DISLIKE'),
    (1, 'LIKE'),
)

class Vote(models.Model):
    user = models.ForeignKey(User)
    content_type = models.ForeignKey(ContentType,
        limit_choices_to={"model__in": ("Thread", "Reply", "Post")}, 
        related_name="votes")
    object_id = models.PositiveIntegerField()
    content_object = generic.GenericForeignKey('content_type', 'object_id')
    vote = models.IntegerField(choices=VOTE_TYPE)

    objects = GetOrNoneManager()

    class Meta():
        unique_together = [('object_id', 'content_type', 'user')]

Vote Serializer:

class VoteSerializer(serializers.ModelSerializer):
    class Meta:
        model = Vote

The view to handle a vote:

@api_view(['POST'])
def discussions_vote(request):

if not request.user.is_authenticated():
    return Response(status=status.HTTP_404_NOT_FOUND)

data = request.DATA

if data['obj_type'] == 'thread':
    content_type = ContentType.objects.get_for_model(Thread)

    print content_type.id

    info = {
        'content_type': content_type.id,
        'user': request.user.id,
        'object_id': data['obj']['id']
    }

    vote = Vote.objects.get_or_none(**info)

    info['vote'] = data['vote']

    ser = VoteSerializer(vote, data=info)

    if ser.is_valid():
        print "Valid"
    else:
        pprint.pprint(ser.errors)

return Response()

request.DATA content:

{u'vote': -1, 
u'obj_type': u'thread', 
u'obj': 
    {
    ...
    u'id': 7, 
    ...
    }
}

When I vote, Django Rest Framework serializer throws an error:

Model content type with pk 149 does not exist.  

149 is the correct id for the ContentType for the Thread model, according to

print content_type.id

I'm pretty much at a loss at what could be causing this...

Aigneis answered 27/2, 2014 at 13:20 Comment(0)
C
4

The issue is probably that you have a generic foreign key in there, which could be linked to any type of model instance, so there's no default way of REST framework determining how to represent the serialized data.

Take a look at the docs on GFKs in serializers here, hopefully it should help get you started... http://www.django-rest-framework.org/api-guide/relations#generic-relationships

If you're still finding it problematic then simply drop out of using serializers altogether, and just perform the validation explicitly in the view, and return a dictionary of whatever values you want to use for the representation.

Calistacalisthenics answered 27/2, 2014 at 15:13 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.