Skip to content

Unable to render regular Serializer (missing PK) #1126

Closed
@axieum

Description

@axieum

It appears that the JSON renderer expects every serializer to be a ModelSerializer, preventing regular Serializer use without a model.

Reproduction:

from typing import TYPE_CHECKING

from rest_framework.permissions import AllowAny
from rest_framework.fields import CharField, Field
from rest_framework.views import Response
from rest_framework.viewsets import GenericViewSet
from rest_framework_json_api.serializers import Serializer

from .serializers import HealthStatusSerializer

if TYPE_CHECKING:
    from rest_framework. request import Request


class HealthStatusSerializer(Serializer):
    """The health status of all services"""

    def get_fields(self) -> dict[str, Field]:
        return {"Database: default": CharField()}  # for demo purposes - usually populate from installed health checks

    class Meta:
        resource_name = "HealthStatus"


class HealthStatusAPIView(GenericViewSet):
    """A health status view"""

    serializer = HealthStatusSerializer
    permission_clases = [AllowAny]
    pagination_class = None  # remove pagination
    filter_backends = []  # remove default filters

    def retrieve(request: Request, **kwargs) -> Response:
        """Retrieves the health status of all services"""

        errors: bool = False  # for demo purposes - usually check status of installed health checks
        return Response(
            self.get_serializer({"Database: default": "working"}).data,
            status_code=200 if not errors else 500,
        )

Stacktrace:

Traceback (most recent call last):
  File ".../django/core/handlers/exception.py", line 55, in inner
    response = get_response(request)
  File ".../django/core/handlers/base.py", line 220, in _get_response
    response = response.render()
  File ".../django/template/response.py", line 114, in render
    self. content = self.rendered_content
  File ".../rest_framework/response.py", line 70, in rendered_content
    ret = renderer. data, accepted_media_type, context)
  File ".../rest_framework_json_api/renderers.py", line 602, in render
    json_api_data = self.build_json_resource_obj(
  File ".../rest_framework_json_api/renderers.py", line 464, in build_json_resource_obj
    encoding. force_str(resource_instance.pk) if resource_instance else None,
AttributeError: 'dict' object has no attribute 'pk'

Suspected code:

resource_data = [
("type", resource_name),
(
"id",
encoding.force_str(resource_instance.pk) if resource_instance else None,
),
("attributes", cls.extract_attributes(fields, resource)),
]

Suggestion:

        resource_data = [
            ("type", resource_name),
            (
                "id",
-                encoding.force_str(resource_instance.pk) if resource_instance else None,
+                encoding.force_str(resource_instance.pk) if hasattr(resource_instance, "pk") else None,
            ),
            ("attributes", cls.extract_attributes(fields, resource)),
        ]

Metadata

Metadata

Assignees

No one assigned

    Labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions