-
Notifications
You must be signed in to change notification settings - Fork 1
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge pull request #39 from maykinmedia/feature/drf-spectacular
Feature/drf spectacular
- Loading branch information
Showing
12 changed files
with
102 additions
and
139 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Empty file.
This file was deleted.
Oops, something went wrong.
This file was deleted.
Oops, something went wrong.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,2 @@ | ||
from .fields import LooseFkFieldExtension # noqa | ||
from .query import LooseFkFilterExtension # noqa |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,26 @@ | ||
""" | ||
Define a field extension that can handle the custom fields. | ||
Requires drf-spectacular, which can be installed as the [openapi] optional group | ||
dependency. | ||
""" | ||
|
||
from drf_spectacular.extensions import OpenApiSerializerFieldExtension | ||
|
||
|
||
class LooseFkFieldExtension(OpenApiSerializerFieldExtension): | ||
target_class = "django_loose_fk.drf.FKOrURLField" | ||
match_subclasses = True | ||
|
||
def map_serializer_field(self, auto_schema, direction): | ||
default_schema = auto_schema._map_serializer_field( | ||
self.target, direction, bypass_extensions=True | ||
) | ||
|
||
return { | ||
**default_schema, | ||
"type": "string", | ||
"format": "uri", | ||
"minLength": self.target.min_length, | ||
"maxLength": self.target.max_length, | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,32 @@ | ||
""" | ||
Define a filter extension that can handle the custom fields. | ||
Requires drf-spectacular, which can be installed as the [openapi] optional group | ||
dependency. | ||
""" | ||
|
||
from drf_spectacular.contrib.django_filters import DjangoFilterExtension | ||
|
||
from .. import filters | ||
|
||
|
||
class LooseFkFilterExtension(DjangoFilterExtension): | ||
"""add "uri" format to loose-fk query params""" | ||
|
||
priority = 1 | ||
|
||
def resolve_filter_field( | ||
self, auto_schema, model, filterset_class, field_name, filter_field | ||
): | ||
schemas = super().resolve_filter_field( | ||
auto_schema, model, filterset_class, field_name, filter_field | ||
) | ||
|
||
if isinstance(filter_field, filters.FkOrUrlFieldFilter): | ||
for schema in schemas: | ||
if "items" in schema["schema"]: | ||
schema["schema"]["items"]["format"] = "uri" | ||
else: | ||
schema["schema"]["format"] = "uri" | ||
|
||
return schemas |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -44,7 +44,7 @@ tests_require = | |
|
||
[options.extras_require] | ||
openapi = | ||
drf-yasg | ||
drf-spectacular | ||
tests = | ||
psycopg2 | ||
pytest | ||
|
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,8 @@ | ||
from django.apps import AppConfig | ||
|
||
|
||
class TestAppConfig(AppConfig): | ||
name = "testapp" | ||
|
||
def ready(self): | ||
from django_loose_fk import oas_extensions # noqa |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,53 +1,45 @@ | ||
from django_filters.rest_framework.backends import DjangoFilterBackend | ||
from drf_yasg import openapi | ||
from drf_yasg.inspectors.field import get_basic_type_info | ||
from drf_spectacular.generators import SchemaGenerator | ||
|
||
from django_loose_fk.inspectors.query import FilterInspector | ||
from testapp.api import ZaakObjectViewSet, ZaakSerializer, ZaakViewSet | ||
|
||
def test_field_schema(): | ||
schema = SchemaGenerator().get_schema(request=None, public=True) | ||
|
||
def test_type_info(): | ||
field = ZaakSerializer().fields["zaaktype"] | ||
|
||
type_info = get_basic_type_info(field) | ||
|
||
assert type_info == { | ||
"type": openapi.TYPE_STRING, | ||
"format": openapi.FORMAT_URI, | ||
"min_length": 1, | ||
zaaktype_schema = schema["components"]["schemas"]["Zaak"]["properties"]["zaaktype"] | ||
assert zaaktype_schema == { | ||
"type": "string", | ||
"format": "uri", | ||
"maxLength": 1000, | ||
"minLength": None, | ||
} | ||
|
||
|
||
def test_filter_introspection(): | ||
viewset = ZaakViewSet() | ||
inspector = FilterInspector(viewset, "/foo", "get", [], None) | ||
filter_backend = DjangoFilterBackend() | ||
def test_filter_schema(): | ||
schema = SchemaGenerator().get_schema(request=None, public=True) | ||
|
||
parameters = inspector.get_filter_parameters(filter_backend) | ||
parameters_schema = schema["paths"]["/zaken/"]["get"]["parameters"] | ||
|
||
assert len(parameters) == 2 | ||
assert len(parameters_schema) == 2 | ||
|
||
zaaktype_param = parameters[0] | ||
assert zaaktype_param.name == "zaaktype" | ||
assert zaaktype_param.type == openapi.TYPE_STRING | ||
assert zaaktype_param.format == openapi.FORMAT_URI | ||
zaaktype_param = parameters_schema[0] | ||
assert zaaktype_param["name"] == "zaaktype" | ||
assert zaaktype_param["schema"]["type"] == "string" | ||
assert zaaktype_param["schema"]["format"] == "uri" | ||
|
||
zaaktype_in_param = parameters[1] | ||
assert zaaktype_in_param.name == "zaaktype__in" | ||
assert zaaktype_in_param.type == openapi.TYPE_STRING | ||
assert zaaktype_in_param.format == openapi.FORMAT_URI | ||
zaaktype_in_param = parameters_schema[1] | ||
assert zaaktype_in_param["name"] == "zaaktype__in" | ||
assert zaaktype_in_param["schema"]["type"] == "array" | ||
assert zaaktype_in_param["schema"]["items"]["type"] == "string" | ||
assert zaaktype_in_param["schema"]["items"]["format"] == "uri" | ||
|
||
|
||
def test_declared_filter_introspection(): | ||
viewset = ZaakObjectViewSet() | ||
inspector = FilterInspector(viewset, "/foo", "get", [], None) | ||
filter_backend = DjangoFilterBackend() | ||
def test_declared_filter_schema(): | ||
schema = SchemaGenerator().get_schema(request=None, public=True) | ||
|
||
parameters = inspector.get_filter_parameters(filter_backend) | ||
parameters_schema = schema["paths"]["/zaakobjectfk/"]["get"]["parameters"] | ||
|
||
assert len(parameters) == 1 | ||
param = parameters[0] | ||
assert len(parameters_schema) == 1 | ||
param = parameters_schema[0] | ||
|
||
assert param.name == "zaak" | ||
assert param.type == openapi.TYPE_STRING | ||
assert param.format == openapi.FORMAT_URI | ||
assert param["name"] == "zaak" | ||
assert param["schema"]["type"] == "string" | ||
assert param["schema"]["format"] == "uri" |