Skip to content

Commit

Permalink
Fix django reusing class-based views
Browse files Browse the repository at this point in the history
  • Loading branch information
maldoinc committed Jan 2, 2025
1 parent f452285 commit 308b5c5
Show file tree
Hide file tree
Showing 4 changed files with 29 additions and 4 deletions.
1 change: 1 addition & 0 deletions test/integration/django/templates/bar.html
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
bar
1 change: 1 addition & 0 deletions test/integration/django/templates/foo.html
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
foo
23 changes: 21 additions & 2 deletions test/integration/django/test_django_integration.py
Original file line number Diff line number Diff line change
@@ -1,10 +1,12 @@
import os
import sys
from pathlib import Path

import django
import pytest
from django.test import Client
from django.urls import include, path
from django.views.generic import TemplateView
from wireup.integration.django import WireupSettings
from wireup.integration.django.apps import get_container

Expand All @@ -24,9 +26,18 @@

MIDDLEWARE = ["wireup.integration.django.wireup_middleware"]

TEMPLATES = [
{
"BACKEND": "django.template.backends.django.DjangoTemplates",
"DIRS": [Path(__file__).parent / "templates/"],
},
]

urlpatterns = [
path(r"", view.index),
path(r"classbased", view.RandomNumberView.as_view()),
path("", view.index),
path("classbased", view.RandomNumberView.as_view()),
path("template_view/foo", TemplateView.as_view(template_name="foo.html")),
path("template_view/bar", TemplateView.as_view(template_name="bar.html")),
path("app_1", include("test.integration.django.apps.app_1.urls")),
path("app_2", include("test.integration.django.apps.app_2.urls")),
]
Expand Down Expand Up @@ -57,6 +68,14 @@ def test_get_random(client: Client):
assert res.content.decode("utf8") == "Hello Test! Debug = True. Your lucky number is 4"


@pytest.mark.parametrize("path", ("foo", "bar"))
def test_get_templated_views(client: Client, path: str):
res = client.get(f"/template_view/{path}")

assert res.status_code == 200
assert res.content.decode("utf8") == path


def test_override(client: Client):
class DummyGreeter(GreeterService):
def greet(self, name: str) -> str:
Expand Down
8 changes: 6 additions & 2 deletions wireup/integration/django/apps.py
Original file line number Diff line number Diff line change
Expand Up @@ -63,12 +63,16 @@ def _autowire(self, resolver: URLResolver) -> None:
self.container._registry.context.remove_dependency_type(target, HttpRequest) # type: ignore[reportPrivateUsage] # noqa: SLF001

def _autowire_class_based_view(self, callback: Any) -> Any:
self.container.register(callback.view_class)
# It is possible in django for one class to serve multiple routes,
# so this needs to create a new type to disambiguate.
# see: https://github.com/maldoinc/wireup/issues/53
wrapped_type = type(f"WireupWrapped{callback.view_class.__name__}", (callback.view_class,), {})
self.container.register(wrapped_type)

# This is taken from the django .as_view() method.
def view(request: HttpRequest, *args: Any, **kwargs: Any) -> Any:
autowired_args: _InjectionResult = self.container._DependencyContainer__callable_get_params_to_inject( # type: ignore[reportAttributeAccessIssue] # noqa: SLF001
callback.view_class
wrapped_type
)

this = callback.view_class(**{**callback.view_initkwargs, **autowired_args.kwargs})
Expand Down

0 comments on commit 308b5c5

Please sign in to comment.