Skip to content
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

Create JSON endpoint for Service and Genre list and detail views #1612

Merged
merged 2 commits into from
Aug 26, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
59 changes: 59 additions & 0 deletions django/cantusdb_project/main_app/mixins.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,59 @@
from typing import Any
from django.http.response import JsonResponse, HttpResponse
from django.http.request import HttpRequest
from django.core.exceptions import ImproperlyConfigured
from django.template.response import TemplateResponse


class JSONResponseMixin:
"""
Mixin to negotiate content type. Designed for use with
DetailView and ListView classes only.

If the request contains an `Accept` header with the value
`application/json`, the response will be a JSON object.
Otherwise, the response will render the HTML template as
usual.

The parent view must define an attribute "json_fields" that
lists the fields to be included in the JSON response.
"""

def render_to_response(
self, context: dict[Any, Any], **response_kwargs: dict[Any, Any]
) -> HttpResponse:
"""
Returns a JSON response if the request accepts JSON.
Otherwise, returns the default response.
"""
try:
request: HttpRequest = self.request # type: ignore[attr-defined]
except AttributeError as exc:
raise ImproperlyConfigured(
"A JSONResponseMixin must be used with a DetailView or ListView."
) from exc
try:
json_fields = self.json_fields # type: ignore[attr-defined]
except AttributeError as exc:
raise ImproperlyConfigured(
"A JSONResponseMixin must define a json_fields attribute."
) from exc
if "application/json" in request.META.get("HTTP_ACCEPT", ""):
obj = context.get("object")
if obj:
obj_json = {}
for field in json_fields:
obj_json[field] = getattr(obj, field)
return JsonResponse({obj.get_verbose_name(): obj_json})
q_s = context["object_list"].values(*json_fields)
q_s_name = str(q_s.model.get_verbose_name_plural())
return JsonResponse({q_s_name: list(q_s)})
try:
template_response: TemplateResponse = super().render_to_response( # type: ignore[misc]
context, **response_kwargs
)
except AttributeError as exc:
raise ImproperlyConfigured(
"A JSONResponseMixin must be used with a DetailView or ListView."
) from exc
return template_response
14 changes: 11 additions & 3 deletions django/cantusdb_project/main_app/tests/make_fakes.py
Original file line number Diff line number Diff line change
Expand Up @@ -251,14 +251,22 @@ def make_fake_feast() -> Feast:
return feast


def make_fake_genre(name=None) -> Genre:
def make_fake_genre(
name: Optional[str] = None,
description: Optional[str] = None,
mass_office: Optional[str] = None,
) -> Genre:
"""Generates a fake Genre object."""
if name is None:
name = faker.lexify("???")
if description is None:
description = faker.sentence()
if mass_office is None:
mass_office = random.choice(["Mass", "Office", "Mass, Office", "Old Hispanic"])
genre = Genre.objects.create(
name=name,
description=faker.sentence(),
mass_office=random.choice(["Mass", "Office", "Mass, Office", "Old Hispanic"]),
description=description,
mass_office=mass_office,
)
return genre

Expand Down
Loading
Loading