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')
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)
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With