-
Notifications
You must be signed in to change notification settings - Fork 270
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Schema Generation for WagtailPagesAPIViewSet #141
Comments
hi! i'm in the process of generalizing the mocked request already used in the special case of API versioning. i suppose it would address your issue. in the meantime, if you use |
Mocked request is the way to go I guess. About Funny thing is, in case of the actual schema generation we don't even need the serializer or request in case of wagtail Pages. It has to be a polymorphic schema and can be generated using the model's APIFields. |
hey @uroybd! i implemented mock requests. with a little bit of luck your issue may be solved with it. can you test it and let me know? |
Great! I'll test it in next 1-2day(s) and will let you know |
i forgot to address one point. of course contributions are welcome! depending on the required changes, you can either contribute to
|
@uroybd i had a quick look into what wagtail is doing. they customize the request as they come in (attach |
Can you give me an example of mock request usage? By far I can just hook extensions without errors which is surely an improvement. Another question, Does |
we introduced global mock requests a few commits ago. i just made it configurable (on master). i should have figured that it wouldn't take long before customization would come up.
that has not come up yet. viewsets by necessity provide more information for introspection so it was not an issue yet. got to check if i quickly put together an incomplete example. # settings.py
SPECTACULAR_SETTINGS = {
'GET_MOCK_REQUEST': 'mysite.urls.build_wagtail_mock_request'
} # urls.py
from drf_spectacular.plumbing import build_mock_request
# load extensions
from mysite.schema import *
api_router = WagtailAPIRouter('wagtailapi')
def build_wagtail_mock_request(method, path, view, original_request, **kwargs):
# default mock request
request = build_mock_request(method, path, view, original_request, **kwargs)
# the added wagtail magic
request.wagtailapi_router = api_router
return request # schema.py
from drf_spectacular.extensions import OpenApiSerializerFieldExtension, OpenApiViewExtension
from drf_spectacular.plumbing import build_basic_type, build_array_type
from drf_spectacular.types import OpenApiTypes
class Fix1(OpenApiSerializerFieldExtension):
target_class = 'wagtail.api.v2.serializers.DetailUrlField'
def map_serializer_field(self, auto_schema, direction):
return build_basic_type(OpenApiTypes.URI)
class Fix2(OpenApiSerializerFieldExtension):
target_class = 'wagtail.api.v2.serializers.TagsField'
def map_serializer_field(self, auto_schema, direction):
return build_array_type(build_basic_type(OpenApiTypes.STR))
class Fix3(Fix1):
target_class = 'wagtail.images.api.v2.serializers.ImageDownloadUrlField'
class Fix4(Fix1):
target_class = 'wagtail.documents.api.v2.serializers.DocumentDownloadUrlField'
class Fix5(Fix1):
target_class = 'wagtail.api.v2.serializers.PageHtmlUrlField'
class Fix6(OpenApiSerializerFieldExtension):
target_class = 'wagtail.api.v2.serializers.TypeField'
def map_serializer_field(self, auto_schema, direction):
return build_basic_type(OpenApiTypes.STR)
class Fix7(Fix6):
target_class = 'wagtail.api.v2.serializers.PageTypeField'
class Fix8(OpenApiViewExtension):
target_class = 'wagtail.api.v2.views.BaseAPIViewSet'
match_subclasses = True
def view_replacement(self):
class Fixed(self.target):
def get_object(self):
return self.get_queryset().model()
return Fixed
class Fix9(OpenApiSerializerFieldExtension):
target_class = 'wagtail.admin.api.serializers.PageChildrenField'
def map_serializer_field(self, auto_schema, direction):
return build_object_type(
properties={
'count': build_basic_type(OpenApiTypes.INT),
'listing_url': build_basic_type(OpenApiTypes.URI),
}
)
class Fix10(OpenApiSerializerFieldExtension):
target_class = 'wagtail.admin.api.serializers.PageStatusField'
def map_serializer_field(self, auto_schema, direction):
return build_object_type(
properties={
'status': build_basic_type(OpenApiTypes.STR),
'live': build_basic_type(OpenApiTypes.BOOL),
'has_unpublished_changes': build_basic_type(OpenApiTypes.BOOL),
}
)
class Fix11(OpenApiSerializerFieldExtension):
target_class = 'wagtail.images.api.fields.ImageRenditionField'
def map_serializer_field(self, auto_schema, direction):
return build_object_type(
properties={
'url': build_basic_type(OpenApiTypes.URI),
'width': build_basic_type(OpenApiTypes.INT),
'height': build_basic_type(OpenApiTypes.INT),
'alt': build_basic_type(OpenApiTypes.STR),
}
) |
had the wrong issue number in commit: 8856ab7 add the mock request function |
i have a few warnings left, which are quite puzzling. wagtail is doing something really strange regarding module modification i think. they somehow inject their serializers in the
the schema already looks somewhat acceptable, but the warnings are not that easy to squash. |
It actually has a |
as i dove in deeper i noticed that too. it is quite "meta". feel free to contribute a blueprint for wagtail if you like, though i'm not sure how and if it is helpful in practice. though currently i don't see much that can be improved in the core to improve wagtail detection. |
closing due to missing action points and being stale. feel free to come back to this if you like and maybe do a blueprint. thanks! |
I tried the extended method mentioned in the doc for Wagtail's
PagesAPIViewSet
with no success.Here's the error:
I browsed the code and tested with some loggers. In
Fix
class I'm not getting anyself.request
which is very important for Wagtail. In fact, everything falls apart if you don't get the request!The text was updated successfully, but these errors were encountered: