1
1
import warnings
2
+ from deepmerge import always_merger
2
3
from urllib .parse import urljoin
3
4
4
5
from django .db .models .fields import related_descriptors as rd
12
13
from rest_framework_json_api import serializers
13
14
from rest_framework_json_api .views import RelationshipView
14
15
15
- #: static OAS 3.0 component definitions that are referenced by AutoSchema .
16
+ #: static OAS 3.0 component definitions that are referenced by SchemaGenerator .
16
17
JSONAPI_COMPONENTS = {
17
18
'schemas' : {
18
19
'jsonapi' : {
@@ -270,11 +271,18 @@ class SchemaGenerator(drf_openapi.SchemaGenerator):
270
271
"""
271
272
Extend DRF's SchemaGenerator to implement jsonapi-flavored generateschema command
272
273
"""
274
+ #: JSONAPI component defintions that are referenced by the generated OAS schema.
275
+ jsonapi_components = JSONAPI_COMPONENTS
276
+ #: optional added OAS schema initialization. Make a subclass and override as needed.
277
+ schema_init = {}
278
+
273
279
def __init__ (self , * args , ** kwargs ):
274
- self .openapi_schema = {}
275
280
super ().__init__ (* args , ** kwargs )
276
281
if not hasattr (self , 'check_duplicate_operation_id' ):
277
282
self .check_duplicate_operation_id = lambda paths : None
283
+ # static JSONAPI fields that get $ref'd to in the view mappings
284
+ # merge in our reference data on top of anything provided by the init.
285
+ self .schema_init = always_merger .merge (self .schema_init , {'components' : self .jsonapi_components })
278
286
279
287
def get_schema (self , request = None , public = False ):
280
288
"""
@@ -283,7 +291,6 @@ def get_schema(self, request=None, public=False):
283
291
"""
284
292
self ._initialise_endpoints ()
285
293
components_schemas = {}
286
- components_schemas .update (JSONAPI_COMPONENTS )
287
294
288
295
# Iterate endpoints generating per method path operations.
289
296
paths = {}
@@ -334,9 +341,6 @@ def get_schema(self, request=None, public=False):
334
341
335
342
paths .setdefault (path , {})
336
343
paths [path ][method .lower ()] = operation
337
- if hasattr (view .schema , 'openapi_schema' ): # TODO: still needed?
338
- # TODO: shallow or deep merge?
339
- self .openapi_schema = {** self .openapi_schema , ** view .schema .openapi_schema }
340
344
341
345
self .check_duplicate_operation_id (paths )
342
346
@@ -345,10 +349,11 @@ def get_schema(self, request=None, public=False):
345
349
'openapi' : '3.0.2' ,
346
350
'info' : self .get_info (),
347
351
'paths' : paths ,
348
- 'components' : components_schemas ,
352
+ 'components' : {
353
+ 'schemas' : components_schemas ,
354
+ }
349
355
}
350
-
351
- return schema
356
+ return always_merger .merge (schema , self .schema_init )
352
357
353
358
def _expand_relationships (self , path , method , view ):
354
359
"""
@@ -437,23 +442,12 @@ class AutoSchema(drf_openapi.AutoSchema):
437
442
"""
438
443
content_types = ['application/vnd.api+json' ]
439
444
440
- def __init__ (self , openapi_schema = None , ** kwargs ):
445
+ def __init__ (self , ** kwargs ):
441
446
"""
442
447
Initialize the JSONAPI OAS schema generator
443
448
:param openapi_schema: dict: OAS 3.0 document with initial values.
444
449
"""
445
450
super ().__init__ (** kwargs )
446
- #: allow initialization of OAS schema doc TODO: still needed?
447
- if openapi_schema is None :
448
- openapi_schema = {}
449
- self .openapi_schema = openapi_schema
450
- # static JSONAPI fields that get $ref'd to in the view mappings
451
- jsonapi_ref = {
452
- 'components' : JSONAPI_COMPONENTS
453
- }
454
- # merge in our reference data on top of anything provided by the init.
455
- # TODO: shallow or deep merge?
456
- self .openapi_schema = {** self .openapi_schema , ** jsonapi_ref }
457
451
458
452
# DRF >= 3.12 (not yet released) has changed a bunch of private methods to public.
459
453
# Accommodate those renamings for DRF < 3.12
0 commit comments