|
@@ -11,6 +11,7 @@ from extras.choices import CustomFieldTypeChoices
|
|
|
from extras.models import CustomField
|
|
from extras.models import CustomField
|
|
|
from ipam.api.serializers import VLANSerializer
|
|
from ipam.api.serializers import VLANSerializer
|
|
|
from ipam.models import VLAN
|
|
from ipam.models import VLAN
|
|
|
|
|
+from netbox.api.fields import SerializedPKRelatedField
|
|
|
from netbox.api.serializers import BaseModelSerializer
|
|
from netbox.api.serializers import BaseModelSerializer
|
|
|
from netbox.config import get_config
|
|
from netbox.config import get_config
|
|
|
from netbox.plugins import register_serializer_resolver
|
|
from netbox.plugins import register_serializer_resolver
|
|
@@ -581,6 +582,178 @@ class GetPrefetchesForSerializerTestCase(TestCase):
|
|
|
['region', 'region__parent'],
|
|
['region', 'region__parent'],
|
|
|
)
|
|
)
|
|
|
|
|
|
|
|
|
|
+ def test_serialized_pk_related_field(self):
|
|
|
|
|
+ class RegionSerializer(BaseModelSerializer):
|
|
|
|
|
+ class Meta:
|
|
|
|
|
+ model = Region
|
|
|
|
|
+ fields = ('id', 'name', 'parent', 'sites')
|
|
|
|
|
+ brief_fields = ('id', 'parent')
|
|
|
|
|
+
|
|
|
|
|
+ class SiteSerializer(BaseModelSerializer):
|
|
|
|
|
+ region = SerializedPKRelatedField(
|
|
|
|
|
+ queryset=Region.objects.all(),
|
|
|
|
|
+ serializer=RegionSerializer,
|
|
|
|
|
+ nested=True,
|
|
|
|
|
+ )
|
|
|
|
|
+
|
|
|
|
|
+ class Meta:
|
|
|
|
|
+ model = Site
|
|
|
|
|
+ fields = ('id', 'region')
|
|
|
|
|
+
|
|
|
|
|
+ self.assertListEqual(
|
|
|
|
|
+ get_prefetches_for_serializer(SiteSerializer),
|
|
|
|
|
+ ['region', 'region__parent'],
|
|
|
|
|
+ )
|
|
|
|
|
+
|
|
|
|
|
+ def test_many_serialized_pk_related_field(self):
|
|
|
|
|
+ class SiteSerializer(BaseModelSerializer):
|
|
|
|
|
+ class Meta:
|
|
|
|
|
+ model = Site
|
|
|
|
|
+ fields = ('id', 'name', 'region', 'group')
|
|
|
|
|
+ brief_fields = ('id', 'region')
|
|
|
|
|
+
|
|
|
|
|
+ class RegionSerializer(BaseModelSerializer):
|
|
|
|
|
+ sites = SerializedPKRelatedField(
|
|
|
|
|
+ queryset=Site.objects.all(),
|
|
|
|
|
+ serializer=SiteSerializer,
|
|
|
|
|
+ nested=True,
|
|
|
|
|
+ many=True,
|
|
|
|
|
+ )
|
|
|
|
|
+
|
|
|
|
|
+ class Meta:
|
|
|
|
|
+ model = Region
|
|
|
|
|
+ fields = ('id', 'sites')
|
|
|
|
|
+
|
|
|
|
|
+ self.assertListEqual(
|
|
|
|
|
+ get_prefetches_for_serializer(RegionSerializer),
|
|
|
|
|
+ ['sites', 'sites__region'],
|
|
|
|
|
+ )
|
|
|
|
|
+
|
|
|
|
|
+ self.assertListEqual(
|
|
|
|
|
+ get_prefetches_for_serializer(RegionSerializer, fields=('id',)),
|
|
|
|
|
+ [],
|
|
|
|
|
+ )
|
|
|
|
|
+
|
|
|
|
|
+ self.assertListEqual(
|
|
|
|
|
+ get_prefetches_for_serializer(RegionSerializer, omit=('sites',)),
|
|
|
|
|
+ [],
|
|
|
|
|
+ )
|
|
|
|
|
+
|
|
|
|
|
+ def test_many_serialized_pk_related_field_not_nested(self):
|
|
|
|
|
+ class SiteSerializer(BaseModelSerializer):
|
|
|
|
|
+ class Meta:
|
|
|
|
|
+ model = Site
|
|
|
|
|
+ fields = ('id', 'name', 'region', 'group')
|
|
|
|
|
+ brief_fields = ('id', 'region')
|
|
|
|
|
+
|
|
|
|
|
+ class RegionSerializer(BaseModelSerializer):
|
|
|
|
|
+ sites = SerializedPKRelatedField(
|
|
|
|
|
+ queryset=Site.objects.all(),
|
|
|
|
|
+ serializer=SiteSerializer,
|
|
|
|
|
+ nested=False,
|
|
|
|
|
+ many=True,
|
|
|
|
|
+ )
|
|
|
|
|
+
|
|
|
|
|
+ class Meta:
|
|
|
|
|
+ model = Region
|
|
|
|
|
+ fields = ('id', 'sites')
|
|
|
|
|
+
|
|
|
|
|
+ self.assertListEqual(
|
|
|
|
|
+ get_prefetches_for_serializer(RegionSerializer),
|
|
|
|
|
+ ['sites', 'sites__region', 'sites__group'],
|
|
|
|
|
+ )
|
|
|
|
|
+
|
|
|
|
|
+ def test_self_referential_serialized_pk_related_field(self):
|
|
|
|
|
+ class RegionSerializer(BaseModelSerializer):
|
|
|
|
|
+ class Meta:
|
|
|
|
|
+ model = Region
|
|
|
|
|
+ fields = ('id', 'parent', 'children')
|
|
|
|
|
+
|
|
|
|
|
+ # The field can only name its own serializer once the class exists.
|
|
|
|
|
+ RegionSerializer._declared_fields['children'] = SerializedPKRelatedField(
|
|
|
|
|
+ queryset=Region.objects.all(),
|
|
|
|
|
+ serializer=RegionSerializer,
|
|
|
|
|
+ many=True,
|
|
|
|
|
+ )
|
|
|
|
|
+
|
|
|
|
|
+ self.assertListEqual(
|
|
|
|
|
+ get_prefetches_for_serializer(RegionSerializer),
|
|
|
|
|
+ ['parent', 'children'],
|
|
|
|
|
+ )
|
|
|
|
|
+
|
|
|
|
|
+ def test_self_referential_serialized_pk_related_field_with_brief_fields(self):
|
|
|
|
|
+ class RegionSerializer(BaseModelSerializer):
|
|
|
|
|
+ class Meta:
|
|
|
|
|
+ model = Region
|
|
|
|
|
+ fields = ('id', 'sites', 'children')
|
|
|
|
|
+ brief_fields = ('id', 'sites')
|
|
|
|
|
+
|
|
|
|
|
+ RegionSerializer._declared_fields['children'] = SerializedPKRelatedField(
|
|
|
|
|
+ queryset=Region.objects.all(),
|
|
|
|
|
+ serializer=RegionSerializer,
|
|
|
|
|
+ nested=True,
|
|
|
|
|
+ many=True,
|
|
|
|
|
+ )
|
|
|
|
|
+
|
|
|
|
|
+ # Re-entering the serializer at brief depth is not a cycle, so brief_fields must expand.
|
|
|
|
|
+ self.assertListEqual(
|
|
|
|
|
+ get_prefetches_for_serializer(RegionSerializer),
|
|
|
|
|
+ ['sites', 'children', 'children__sites'],
|
|
|
|
|
+ )
|
|
|
|
|
+
|
|
|
|
|
+ def test_mutually_referential_serialized_pk_related_fields(self):
|
|
|
|
|
+ class RegionSerializer(BaseModelSerializer):
|
|
|
|
|
+ class Meta:
|
|
|
|
|
+ model = Region
|
|
|
|
|
+ fields = ('id', 'sites')
|
|
|
|
|
+
|
|
|
|
|
+ class SiteSerializer(BaseModelSerializer):
|
|
|
|
|
+ region = SerializedPKRelatedField(
|
|
|
|
|
+ queryset=Region.objects.all(),
|
|
|
|
|
+ serializer=RegionSerializer,
|
|
|
|
|
+ )
|
|
|
|
|
+
|
|
|
|
|
+ class Meta:
|
|
|
|
|
+ model = Site
|
|
|
|
|
+ fields = ('id', 'region')
|
|
|
|
|
+
|
|
|
|
|
+ RegionSerializer._declared_fields['sites'] = SerializedPKRelatedField(
|
|
|
|
|
+ queryset=Site.objects.all(),
|
|
|
|
|
+ serializer=SiteSerializer,
|
|
|
|
|
+ many=True,
|
|
|
|
|
+ )
|
|
|
|
|
+
|
|
|
|
|
+ self.assertListEqual(
|
|
|
|
|
+ get_prefetches_for_serializer(RegionSerializer),
|
|
|
|
|
+ ['sites', 'sites__region'],
|
|
|
|
|
+ )
|
|
|
|
|
+
|
|
|
|
|
+ def test_serializer_class_reused_on_sibling_fields(self):
|
|
|
|
|
+ class TargetRegionSerializer(BaseModelSerializer):
|
|
|
|
|
+ class Meta:
|
|
|
|
|
+ model = Region
|
|
|
|
|
+ fields = ('id', 'sites')
|
|
|
|
|
+
|
|
|
|
|
+ class RegionSerializer(BaseModelSerializer):
|
|
|
|
|
+ parent = SerializedPKRelatedField(
|
|
|
|
|
+ queryset=Region.objects.all(),
|
|
|
|
|
+ serializer=TargetRegionSerializer,
|
|
|
|
|
+ )
|
|
|
|
|
+ children = SerializedPKRelatedField(
|
|
|
|
|
+ queryset=Region.objects.all(),
|
|
|
|
|
+ serializer=TargetRegionSerializer,
|
|
|
|
|
+ many=True,
|
|
|
|
|
+ )
|
|
|
|
|
+
|
|
|
|
|
+ class Meta:
|
|
|
|
|
+ model = Region
|
|
|
|
|
+ fields = ('id', 'parent', 'children')
|
|
|
|
|
+
|
|
|
|
|
+ self.assertListEqual(
|
|
|
|
|
+ get_prefetches_for_serializer(RegionSerializer),
|
|
|
|
|
+ ['parent', 'parent__sites', 'children', 'children__sites'],
|
|
|
|
|
+ )
|
|
|
|
|
+
|
|
|
|
|
|
|
|
class _ResolvedSerializerA(Serializer):
|
|
class _ResolvedSerializerA(Serializer):
|
|
|
pass
|
|
pass
|