Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

GenericRelatedObjectManager not JSON serializable

I'm using Django REST Framework and am trying to create a generic relation. When I try to view DeviceModel it throws the error

<django.contrib.contenttypes.fields.GenericRelatedObjectManager object at 0x2b7e6d0> is not JSON serializable

The documentation states fairly clearly that reverse generic relations should work, so what am I doing wrong?

My models:

class GenericDevice(models.Model):
    #other fields...
    content_type = models.ForeignKey(ContentType)
    object_id = models.PositiveIntegerField()
    device_model = GenericForeignKey('content_type', 'object_id')

class DeviceModel(models.Model):
    #other fields...
    generic_model = GenericRelation(GenericDevice)

Serializers:

class DeviceModelSerializer(serializers.ModelSerializer):

    generic_model = serializers.PrimaryKeyRelatedField(
        queryset = models.GenericDevice.objects.all()
    )

    class Meta:
        model = models.SSDDeviceModel
        fields = (...other fields..., 'generic_model')

class DeviceModelRelatedField(serializers.PrimaryKeyRelatedField):
    def to_representation(self, value):
        if isinstance(value, models.DeviceModel):
            serializer = DeviceModelSerializer(value)
        else:
            raise Exception('Unexpected device model')
        return serializer.data

class GenericDeviceSerializer(serializers.ModelSerializer):
    device_model = DeviceModelRelatedField(queryset=models.DeviceModel.objects.all())

    class Meta:
        model = models.GenericDevice
        fields = ('device_model')
like image 246
Collin Reynolds Avatar asked Apr 30 '15 17:04

Collin Reynolds


1 Answers

I ran into this problem too just now. I think I solved it with the following code, loosely modeled off of the Django REST docs - Generic Relationships.

(I hope it helps. I'm new to Django. I'll update this if I can make it more elegant).

My Models:

from django.contrib.auth.models import User
from django.db import models
from django_extensions.db.models import TimeStampedModel
from django.contrib.contenttypes.fields import GenericForeignKey, GenericRelation
from django.contrib.contenttypes.models import ContentType


class TaggedItem(models.Model):
    """
    Tags arbitrary model instances using a generic relation.
    """
    tag_name = models.SlugField()
    content_type = models.ForeignKey(ContentType)
    object_id = models.PositiveIntegerField()
    tagged_object = GenericForeignKey('content_type', 'object_id')
    user_created = models.BooleanField(default=True)

    class Meta:
        verbose_name = 'tag'
        verbose_name_plural = 'tags'

    def __str__(self):
        return self.tag_name 


class Bookmark(TimeStampedModel):
    """
    A bookmark consists of a URL, and 0 or more descriptive tags.
    """
    user = models.ForeignKey(User, verbose_name='user', related_name='bookmarks')
    url = models.URLField()
    title = models.CharField('title', max_length=255)
    description = models.TextField('description', blank=True)
    tags = GenericRelation(TaggedItem)

    class Meta:
        unique_together = ("url", "user")
        verbose_name = 'bookmark'
        verbose_name_plural = 'bookmarks'

    def __str__(self):
        return '%s (%s)' % (self.title, self.user)

My Serializers:

# 3rd Party
from rest_framework import serializers
from rest_framework.pagination import PageNumberPagination

# Market Builder
from market_builder.serializers import HATEOASMixin
from . import models


class BookmarkPagination(PageNumberPagination):
    """Bookmark pagination serialization."""

    page_size = 10
    page_size_query_param = 'page_size'


class TaggedObjectRelatedField(serializers.RelatedField):
    """
    Serialize bookmark instances using a bookmark serializer.
    """

    def to_representation(self, value):
        if isinstance(value, models.Bookmark):
            serializer = BookmarkSerializer(value)
        else:
            raise Exception('Unexcepted type of tagged object')

        return serializer.data


class TaggedItemSerializer(serializers.ModelSerializer):
    """Tagged Item serialization."""

    class Meta:
        model = models.TaggedItem
        fields = [
            'tag_name',
            'user_created',
            'object_id',
        ]


class BookmarkSerializer(HATEOASMixin, serializers.ModelSerializer):
    """Bookmark serialization."""

    links = serializers.SerializerMethodField()
    tags = TaggedItemSerializer(many=True)

    class Meta:
        model = models.Bookmark
        fields = [
            'id',
            'url',
            'title',
            'description',
            'created',
            'modified',
            'tags',
            'links',
        ]

    def get_links(self, bookmark):
        links = super().get_links(bookmark)
        return links

My Admin:

from django.contrib import admin
from django.contrib.contenttypes import admin as cadmin

from .models import Bookmark, TaggedItem


class TaggedItemInline(cadmin.GenericTabularInline):
    model = TaggedItem


class BookmarkAdmin(admin.ModelAdmin):
    list_display = ('title', 'url', 'user', )
    list_filter = ('user', )
    search_fields = ['url', 'title']
    inlines = [
        TaggedItemInline,
    ]


class TaggedItemAdmin(admin.ModelAdmin):
    list_display = ('tag_name', )

admin.site.register(Bookmark, BookmarkAdmin)
admin.site.register(TaggedItem, TaggedItemAdmin)
like image 169
some_name_dev Avatar answered Nov 01 '22 22:11

some_name_dev