Coverage for apis_core/generic/serializers.py: 63%
49 statements
« prev ^ index » next coverage.py v7.6.8, created at 2024-12-20 09:24 +0000
« prev ^ index » next coverage.py v7.6.8, created at 2024-12-20 09:24 +0000
1from django.contrib.contenttypes.models import ContentType
2from django.shortcuts import get_object_or_404
3from rest_framework.reverse import reverse
4from rest_framework.serializers import (
5 CharField,
6 HyperlinkedModelSerializer,
7 HyperlinkedRelatedField,
8 IntegerField,
9 Serializer,
10 SerializerMethodField,
11)
14class GenericHyperlinkedRelatedField(HyperlinkedRelatedField):
15 def get_url(self, obj, view_name, request, format):
16 contenttype = ContentType.objects.get_for_model(obj, for_concrete_model=True)
17 url_kwargs = {"contenttype": contenttype, "pk": obj.pk}
18 return reverse(
19 "apis_core:generic:genericmodelapi-detail",
20 kwargs=url_kwargs,
21 request=request,
22 format=format,
23 )
25 def use_pk_only_optimization(self):
26 # We have the complete object instance already. We don't need
27 # to run the 'only get the pk for this relationship' code.
28 return False
31class GenericHyperlinkedIdentityField(GenericHyperlinkedRelatedField):
32 def __init__(self, view_name=None, **kwargs):
33 assert view_name is not None, "The `view_name` argument is required."
34 kwargs["read_only"] = True
35 kwargs["source"] = "*"
36 super().__init__(view_name, **kwargs)
39class GenericHyperlinkedModelSerializer(HyperlinkedModelSerializer):
40 serializer_related_field = GenericHyperlinkedRelatedField
41 serializer_url_field = GenericHyperlinkedIdentityField
44def serializer_factory(
45 model, serializer=GenericHyperlinkedModelSerializer, fields="__all__", **kwargs
46):
47 defaultmeta = type(str("Meta"), (object,), {"fields": fields})
48 meta = getattr(serializer, "Meta", defaultmeta)
49 meta.model = model
50 serializer = type(
51 str("%sModelSerializer" % model._meta.object_name),
52 (serializer,),
53 {"Meta": meta},
54 )
55 return serializer
58class ContentTypeInstanceSerializer(Serializer):
59 id = IntegerField(required=True)
60 content_type = CharField(required=True)
62 def to_internal_value(self, data):
63 data = super().to_internal_value(data)
64 app_label, model = data.get("content_type").split(".")
65 content_type = get_object_or_404(ContentType, app_label=app_label, model=model)
66 return get_object_or_404(content_type.model_class(), pk=data.get("id"))
69class SimpleObjectSerializer(Serializer):
70 url = GenericHyperlinkedIdentityField(
71 view_name="apis_core:generic:genericmodelapi-detail"
72 )
73 label = SerializerMethodField()
74 content_type_key = SerializerMethodField()
75 content_type_name = SerializerMethodField()
77 class Meta:
78 fields = ["url", "label", "content_type_key", "content_type_name"]
80 def get_label(self, obj) -> str:
81 return str(obj)
83 def get_content_type_key(self, obj) -> str:
84 content_type = ContentType.objects.get_for_model(obj)
85 return f"{content_type.app_label}.{content_type.model}"
87 def get_content_type_name(self, obj) -> str:
88 content_type = ContentType.objects.get_for_model(obj)
89 return content_type.name