title: Django serializer requiring a dict instead of a model instance
body: <p>I'm trying to make a really simple serialization in a viewset in django, but my serializer, which should require the instance to be serialized, is requiring a dict.</p>
  <p>This is my custom serializer:</p>
  <pre class="lang-py prettyprint-override"><code>class JSONAPIModelSerializer(serializers.ModelSerializer):
  
      def __init__(cls, *args, **kwargs):
          if kwargs.get('many', False) is True:
              context = kwargs.get('context', {})
              context.update({'is_many': True})
              kwargs.update({'context': context})
  
          return super().__init__(cls, *args, **kwargs)
  
      def format_object(self, instance, attributes: dict, meta = None, relationships = None, links = None, is_many: bool = False) -&gt; dict:
          jsonapi_data = {
              'type': instance.__class__.__name__.lower() if not getattr(self.Meta, 'resource_type', None) else None,
              'id': str(instance.id),
              'attributes': attributes,
          }
          jsonapi_data.update({'relationships': relationships}) if relationships else None
          if is_many:
              jsonapi_data = {
                  'data': jsonapi_data
              }
          jsonapi_data.update({'meta': meta}) if meta else None
          jsonapi_data.update({'links': links}) if links else None
          return jsonapi_data
  
      def get_attrs(self, instance):
          return {}
      
      def get_meta(self, instance):
          return None
  
      def get_links(self, instance):
          return None
  
      def get_relationships(self, instance):
          return None
  
      def to_representation(self, instance):
          return self.format_object(
              instance=instance,
              is_many=self.context.get('is_many', False),
              attributes=self.get_attrs(instance),
              meta=self.get_meta(instance),
              relationships=self.get_relationships(instance),
              links=self.get_links(instance)
          )
  
  class AnimeSerializer(JSONAPIModelSerializer):
  
      class Meta:
          model = Anime
          fields = '__all__'
          resource_name = 'anime'
  
      def get_attrs(self, instance):
          return {
              'titles': {
                  'en': instance.title_en,
                  'es': instance.title_es,
                  'en_jp': instance.title_ro,
                  'ja_jp': instance.title_jp
              },
              'titleCanonical': instance.title_canonical,
              'abbreviatedTitles': [i.value for i in instance.titles_abbreviated.all()],
              'otherTitles': [i.value for i in instance.titles_others.all()],
              'description': instance.description,
              'coverImage': {
                  'tiny': instance.cover.tiny.url if getattr(instance.cover, 'tiny') is not None else None,
                  'small': instance.cover.small.url if getattr(instance.cover, 'small') is not None else None,
                  'medium': instance.cover.medium.url if getattr(instance.cover, 'medium') is not None else None,
                  'large': instance.cover.large.url if getattr(instance.cover, 'large') is not None else None,
                  'xlarge': instance.cover.xlarge.url if getattr(instance.cover, 'xlarge') is not None else None,
              },
              'bannerImage': {
                  'tiny': getattr(getattr(instance.banner, 'tiny', None), 'url', None),
                  'small': getattr(getattr(instance.banner, 'small', None), 'url', None),
                  'medium': getattr(getattr(instance.banner, 'medium', None), 'url', None),
                  'large': getattr(getattr(instance.banner, 'large', None), 'url', None),
                  'xlarge': getattr(getattr(instance.banner, 'xlarge', None), 'url', None),
              },
              'genres': [i.name for i in instance.genres.all()],
              'demography': instance.demography,
              'ageRating': instance.get_age_rating_display(),
              'showType': instance.get_show_type_display(),
              'rating': instance.rating,
              'broadcasting': {
                  'startDate': instance.date_start,
                  'endDate': instance.date_start,
                  'day': instance.get_broadcasting_day_display(),
                  'time': instance.broadcasting_time,
              },
              'status': instance.get_status_display(),
              'duration': _('%(min)s min per ep') % {'min': instance.episode_length} if instance.episode_count != 1 else _('%(min)s min') % {'min': instance.episode_length},
              'nsfw': instance.nsfw,
              'source': instance.get_source_display(),
          }
  
      def get_links(self, instance):
          return {
              &quot;self&quot;: &quot;https://api.anibase.co/v1/anime/%s&quot; % instance.id
          }
  
      def get_relationships(self, instance):
          return {
              &quot;characters&quot;: {
                  &quot;links&quot;: {
                      &quot;related&quot;: &quot;https://api.anibase.co/v1/anime/%s/relationships/characters&quot; % instance.id,
                      &quot;self&quot;: &quot;https://api.anibase.co/v1/anime/%s/characters&quot; % instance.id
                  },
                  &quot;data&quot;: [{'type': 'character', 'id': str(i.character.id), 'meta': { 'role': i.get_character_type_display() }} for i in instance.characters.all()]
              },
              &quot;staff&quot;: {
                  &quot;links&quot;: {
                      &quot;related&quot;: &quot;https://api.anibase.co/v1/anime/%s/relationships/staff&quot; % instance.id,
                      &quot;self&quot;: &quot;https://api.anibase.co/v1/anime/%s/staff&quot; % instance.id
                  },
                  &quot;data&quot;: [{'type': 'people', 'id': str(i.staff.id), 'meta': { 'roles': [role.name for role in i.roles.all()] }} for i in instance.staff.all()]
              }
          }
  
      def get_meta(self, instance):
          return {
              'createdAt': instance.created_at,
              'updatedAt': instance.updated_at,
          }
  </code></pre>
  <p>And this is my <code>ViewSet</code>:</p>
  <pre class="lang-py prettyprint-override"><code>class JSONAPIModelViewSet(viewsets.ViewSet, GenericAPIView):
      &quot;&quot;&quot;
      A viewset designed to implement the JSON:API spec by default.
      &quot;&quot;&quot;
  
      serializer_class: serializers.Serializer = None
      filterset_class: django_filters.FilterSet = None
      pagination_class = JSONAPILimitOffsetPagination
      lookup_field = &quot;id&quot;
  
      def __init__(self, *args, **kwargs: Any) -&gt; None:
          super().__init__(*args, **kwargs)
  
      def get_queryset(self):
          return self.serializer_class.Meta.model.objects.all()
  
      def list(self, request, *args, **kwargs):
          queryset = self.filter_queryset(self.get_queryset())
  
          page = self.paginate_queryset(queryset)
          if page is not None:
              serializer = self.get_serializer(page, many=True)
              return self.get_paginated_response(serializer.data)
  
          serializer = self.get_serializer(queryset, many=True)
          return Response(serializer.data)
  
      def retrieve(self, request, *args, **kwargs):
          instance = self.get_object()
          serializer = self.get_serializer(instance)
          if serializer.is_valid():
              return Response(serializer.data)
          return Response(serializer.errors)
  
  
  class AnimeViewSet(JSONAPIModelViewSet):
      serializer_class = AnimeSerializer
      filterset_class = AnimeFilter
      relationships = ['characters', 'staff']
  </code></pre>
  <p>However, whenever I try to make a request to the <code>retrieve</code> view, I get the following response:</p>
  <pre class="lang-json prettyprint-override"><code>{
     non_field_errors: [
        &quot;Invalid data. Expected a dictionary, but got Anime.&quot;
     ]
  }
  </code></pre>
  <p>I've tried replacing the <code>self.get_serializer(instance)</code> with <code>self.get_serializer(data={})</code>, but now the instance passed to <code>to_representation</code> in the serializer is an instance of itself. I've tried raising errors to see where the code stopped and the exception is raised in the <code>is_valid()</code> check. If I do <code>is_valid(raise_exception=False)</code>, I get an empty JSON as a response. I even tried to explictly put the <code>AnimeSerializer</code> replacing <code>self.get_serializer()</code> but it's no use.</p>
  <p>How can I get it to accept the instance as an actual data parameter and stop requiring a dict?</p>
  <p>Edit: This only happens with the <code>retrieve</code> view, works fine with <code>list</code> view.</p>