diff --git a/rest_framework/schemas/generators.py b/rest_framework/schemas/generators.py index 3e927527c..a9fa15b87 100644 --- a/rest_framework/schemas/generators.py +++ b/rest_framework/schemas/generators.py @@ -51,6 +51,19 @@ def is_api_view(callback): return (cls is not None) and issubclass(cls, APIView) +INSERT_INTO_COLLISION_FMT = """ +Schema Naming Collision. + +coreapi.Link for URL path {value_url} cannot be inserted into schema. +Position conflicts with coreapi.Link for URL path {target_url}. + +Attemped to insert link with keys: {keys}. + +Adjust URLs to avoid naming collision or override `SchemaGenerator.get_keys()` +to customise schema structure. +""" + + def insert_into(target, keys, value): """ Nested dictionary insertion. @@ -64,7 +77,15 @@ def insert_into(target, keys, value): if key not in target: target[key] = {} target = target[key] - target[keys[-1]] = value + try: + target[keys[-1]] = value + except TypeError: + msg = INSERT_INTO_COLLISION_FMT.format( + value_url=value.url, + target_url=target.url, + keys=keys + ) + raise ValueError(msg) def is_custom_action(action): diff --git a/tests/test_schemas.py b/tests/test_schemas.py index 0c2589394..6555a13b8 100644 --- a/tests/test_schemas.py +++ b/tests/test_schemas.py @@ -778,7 +778,9 @@ class TestURLNamingCollisions(TestCase): ] generator = SchemaGenerator(title='Naming Colisions', patterns=patterns) - schema = generator.get_schema() + + with pytest.raises(ValueError): + generator.get_schema() def test_manually_routing_generic_view(self): patterns = [ @@ -793,7 +795,9 @@ class TestURLNamingCollisions(TestCase): ] generator = SchemaGenerator(title='Naming Colisions', patterns=patterns) - schema = generator.get_schema() + + with pytest.raises(ValueError): + generator.get_schema() def test_from_router(self): patterns = [ @@ -801,4 +805,6 @@ class TestURLNamingCollisions(TestCase): ] generator = SchemaGenerator(title='Naming Colisions', patterns=patterns) - schema = generator.get_schema() + + with pytest.raises(ValueError): + generator.get_schema()