diff --git a/worf/renderers.py b/worf/renderers.py index 51e313b..6246054 100644 --- a/worf/renderers.py +++ b/worf/renderers.py @@ -1,15 +1,58 @@ from django.http import HttpResponse, JsonResponse from django.template.response import TemplateResponse +from worf.casing import snake_to_camel from worf.conf import settings +from worf.shortcuts import field_list -def browsable_response(request, response, status_code=200): +def browsable_response(request, response, status_code, view): template = "worf/api.html" + serializer = view.get_serializer() + + include = field_list(view.bundle.get("include", [])) + search = field_list(view.bundle.get("search", []), delimiter="__") + + filter_fields = [ + (transform_field(field), bool(field in view.bundle)) + for field in getattr(view, "filter_fields", []) + ] + include_fields = [ + (transform_field(field, "."), bool(field in include or not include)) + for field in getattr(view, "include_fields", {}).keys() + ] + search_fields = [ + (transform_field(field, "."), bool(field in search or not search)) + for field in getattr(view, "search_fields", []) + ] + context = dict( content=response.content.decode("utf-8"), + fields=[ + ( + "Filters", + sorted(filter_fields), + len([field for field, active in filter_fields if active]), + ), + ( + "Include", + sorted(include_fields), + len(include), + ), + ( + "Search", + sorted(search_fields), + len(search or search_fields) if view.bundle.get("q") else 0, + ), + ], + lookup_kwargs=getattr(view, "lookup_kwargs", {}), + payload=view.bundle, response=response, + serializer=serializer, + serializer_name=type(serializer).__name__, settings=settings, + view=view, + view_name=type(view).__name__, ) response = TemplateResponse(request, template, context=context) @@ -19,7 +62,7 @@ def browsable_response(request, response, status_code=200): return response -def render_response(request, data, status_code=200): +def render_response(request, data, status_code, view): is_browsable = ( settings.WORF_BROWSABLE_API and "text/html" in request.headers.get("Accept", "") @@ -35,6 +78,10 @@ def render_response(request, data, status_code=200): response.status_code = status_code if is_browsable: - response = browsable_response(request, response, status_code) + response = browsable_response(request, response, status_code, view) return response + + +def transform_field(field, delimiter="__"): + return delimiter.join(map(snake_to_camel, field.split("__"))) diff --git a/worf/serializers.py b/worf/serializers.py index 53eeada..cd18ad2 100644 --- a/worf/serializers.py +++ b/worf/serializers.py @@ -1,7 +1,6 @@ import marshmallow from marshmallow.decorators import * # noqa: F401, F403 -from django.core.exceptions import ImproperlyConfigured from django.db.models.fields.files import FieldFile from worf import fields @@ -16,26 +15,22 @@ class SerializeModels: serializer = None staff_serializer = None - def get_serializer(self): + def get_serializer(self, **kwargs): serializer = self.serializer if self.staff_serializer and self.request.user.is_staff: # pragma: no cover serializer = self.staff_serializer - if not serializer: # pragma: no cover - msg = f"{self.__class__.__name__}.get_serializer() did not return a serializer" - raise ImproperlyConfigured(msg) - - return serializer(**self.get_serializer_kwargs()) + return serializer and serializer(**self.get_serializer_kwargs(**kwargs)) def get_serializer_context(self): return {} - def get_serializer_kwargs(self): + def get_serializer_kwargs(self, include=[], exclude=[]): context = dict(request=self.request, **self.get_serializer_context()) only = set(field_list(self.bundle.get("fields", []))) - include = field_list(self.bundle.get("include", [])) - exclude = set(self.include_fields.keys()) - set(include) + include = include or field_list(self.bundle.get("include", [])) + exclude = exclude or set(self.include_fields.keys()) - set(include) return dict(context=context, only=only, exclude=exclude) def load_serializer(self): diff --git a/worf/templates/worf/base.html b/worf/templates/worf/base.html index 159f8be..2488989 100644 --- a/worf/templates/worf/base.html +++ b/worf/templates/worf/base.html @@ -7,17 +7,17 @@ {% endblock %} - {{ settings.WORF_API_NAME }}: {{ request.get_full_path }} + {{ view_name }} | {{ settings.WORF_API_NAME }}: {{ request.get_full_path }} {% block style %} -