Skip to content

Commit

Permalink
#105 add proper context manager for passing request to wagtail pages …
Browse files Browse the repository at this point in the history
…+ test
  • Loading branch information
ephes committed Sep 7, 2023
1 parent 8c4aabc commit e067354
Show file tree
Hide file tree
Showing 2 changed files with 50 additions and 2 deletions.
30 changes: 28 additions & 2 deletions cast/api/views.py
Original file line number Diff line number Diff line change
@@ -1,10 +1,12 @@
import logging
from collections import OrderedDict
from collections.abc import Iterator
from contextlib import contextmanager
from typing import Any, cast

from django.contrib.auth.mixins import LoginRequiredMixin
from django.db.models import QuerySet
from django.http import JsonResponse
from django.http import HttpRequest, JsonResponse
from django.urls import reverse
from django.views.generic import CreateView
from rest_framework import generics, status
Expand Down Expand Up @@ -203,11 +205,35 @@ def get_filtered_queryset(self) -> QuerySet:
return filterset.qs

def get_queryset(self):
ProxyRequest.request = self.request
if self.request.GET.dict().get("use_post_filter", "false") == "true":
return self.get_filtered_queryset()
return super().get_queryset()

def dispatch(self, request, *args, **kwargs):
"""
Override dispatch to set request on ProxyRequest to be able to use
the real request in page models. This is needed for example to select
the correct template base directory (theme) from `request.session` which
would otherwise not be available.
Putting this into get_queryset() would not work because `ProxyRequest.request`
would be None again before it gets used in the `page.get_description` method.
"""

@contextmanager
def tunneled_request(_request: HttpRequest) -> Iterator:
"""
Set request on ProxyRequest for use in page models temporarily.
"""
ProxyRequest.request = _request
try:
yield
finally:
ProxyRequest.request = None

with tunneled_request(request):
return super().dispatch(request, *args, **kwargs)


# Wagtail API
wagtail_api_router = WagtailAPIRouter("cast:api:wagtail")
Expand Down
22 changes: 22 additions & 0 deletions tests/api_test.py
Original file line number Diff line number Diff line change
Expand Up @@ -320,3 +320,25 @@ def test_update_theme_invalid(api_client):
print(result)
assert result["error"] == "Theme slug is invalid"
assert api_client.session.get("template_base_dir") is None


@pytest.mark.django_db
def test_render_html_with_theme_from_session(api_client, post):
# Given we have custom theme set in the session
r = api_client.post(
# FIXME there's some way to update the session more elegantly
# use this instead of the post request
reverse("cast:api:theme-update"),
{"theme_slug": "plain"},
format="json",
)
assert r.status_code == 200

# When we request the blog post via api
url = reverse("cast:api:wagtail:pages:detail", kwargs={"pk": post.pk})
r = api_client.get(url, format="json")
assert r.status_code == 200

# Then we expect the blog post to be rendered with the theme from the session
assert r.context.get("template_base_dir") == "plain"
assert all([t.name.startswith("cast/plain/") for t in r.templates])

0 comments on commit e067354

Please sign in to comment.