Resolve drf-yasg ref_name conflicts

This solves the problem of distinct serializers being confused because they have the same class name (e.g. `InterfaceSerializer`)

Fixes #2065.
This commit is contained in:
Cristi Vîjdea 2019-03-04 03:24:45 +02:00
parent b381bdec27
commit 3a62e9a322
2 changed files with 22 additions and 2 deletions

View File

@ -1,14 +1,24 @@
from drf_yasg import openapi from drf_yasg import openapi
from drf_yasg.inspectors import FieldInspector, NotHandled, PaginatorInspector, FilterInspector, SwaggerAutoSchema from drf_yasg.inspectors import FieldInspector, NotHandled, PaginatorInspector, FilterInspector, SwaggerAutoSchema
from drf_yasg.utils import get_serializer_ref_name
from rest_framework.fields import ChoiceField from rest_framework.fields import ChoiceField
from rest_framework.relations import ManyRelatedField from rest_framework.relations import ManyRelatedField
from taggit_serializer.serializers import TagListSerializerField from taggit_serializer.serializers import TagListSerializerField
from dcim.api.serializers import InterfaceSerializer as DCIMInterfaceSerializer
from virtualization.api.serializers import InterfaceSerializer as VirtualMachineInterfaceSerializer
from extras.api.customfields import CustomFieldsSerializer from extras.api.customfields import CustomFieldsSerializer
from utilities.api import ChoiceField, SerializedPKRelatedField, WritableNestedSerializer from utilities.api import ChoiceField, SerializedPKRelatedField, WritableNestedSerializer
# this might be ugly, but it limits drf_yasg-specific code to this file
DCIMInterfaceSerializer.Meta.ref_name = 'DCIMInterface'
VirtualMachineInterfaceSerializer.Meta.ref_name = 'VirtualMachineInterface'
class NetBoxSwaggerAutoSchema(SwaggerAutoSchema): class NetBoxSwaggerAutoSchema(SwaggerAutoSchema):
writable_serializers = {}
def get_request_serializer(self): def get_request_serializer(self):
serializer = super().get_request_serializer() serializer = super().get_request_serializer()
@ -21,7 +31,17 @@ class NetBoxSwaggerAutoSchema(SwaggerAutoSchema):
properties[child_name] = None properties[child_name] = None
if properties: if properties:
writable_class = type('Writable' + type(serializer).__name__, (type(serializer),), properties) if type(serializer) not in self.writable_serializers:
writable_name = 'Writable' + type(serializer).__name__
meta_class = getattr(type(serializer), 'Meta', None)
if meta_class:
ref_name = 'Writable' + get_serializer_ref_name(serializer)
writable_meta = type('Meta', (meta_class,), {'ref_name': ref_name})
properties['Meta'] = writable_meta
self.writable_serializers[type(serializer)] = type(writable_name, (type(serializer),), properties)
writable_class = self.writable_serializers[type(serializer)]
serializer = writable_class() serializer = writable_class()
return serializer return serializer

View File

@ -8,7 +8,7 @@ django-taggit==0.23.0
django-taggit-serializer==0.1.7 django-taggit-serializer==0.1.7
django-timezone-field==3.0 django-timezone-field==3.0
djangorestframework==3.9.0 djangorestframework==3.9.0
drf-yasg[validation]==1.11.1 drf-yasg[validation]==1.14.0
graphviz==0.10.1 graphviz==0.10.1
Markdown==2.6.11 Markdown==2.6.11
netaddr==0.7.19 netaddr==0.7.19