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

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) 

12 

13 

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 ) 

24 

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 

29 

30 

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) 

37 

38 

39class GenericHyperlinkedModelSerializer(HyperlinkedModelSerializer): 

40 serializer_related_field = GenericHyperlinkedRelatedField 

41 serializer_url_field = GenericHyperlinkedIdentityField 

42 

43 

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 

56 

57 

58class ContentTypeInstanceSerializer(Serializer): 

59 id = IntegerField(required=True) 

60 content_type = CharField(required=True) 

61 

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")) 

67 

68 

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() 

76 

77 class Meta: 

78 fields = ["url", "label", "content_type_key", "content_type_name"] 

79 

80 def get_label(self, obj) -> str: 

81 return str(obj) 

82 

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}" 

86 

87 def get_content_type_name(self, obj) -> str: 

88 content_type = ContentType.objects.get_for_model(obj) 

89 return content_type.name