From 4d11ea1ef01eba14b3a48a727f07f723f782fd84 Mon Sep 17 00:00:00 2001
From: Clifford Gama <cliffygamy@gmail.com>
Date: Tue, 22 Oct 2024 14:12:02 +0200
Subject: [PATCH] Fixed #28999 -- Documented how to reverse a class-based view
 by instance.

Co-authored-by: Sarah Boyce <42296566+sarahboyce@users.noreply.github.com>
---
 docs/ref/urlresolvers.txt          | 23 ++++++++++++++++++++++-
 tests/urlpatterns_reverse/tests.py |  4 ++--
 tests/urlpatterns_reverse/urls.py  |  2 +-
 tests/urlpatterns_reverse/views.py |  4 ++--
 4 files changed, 27 insertions(+), 6 deletions(-)

diff --git a/docs/ref/urlresolvers.txt b/docs/ref/urlresolvers.txt
index b335d1fc39..3c3be76e75 100644
--- a/docs/ref/urlresolvers.txt
+++ b/docs/ref/urlresolvers.txt
@@ -13,7 +13,8 @@ your code, Django provides the following function:
 .. function:: reverse(viewname, urlconf=None, args=None, kwargs=None, current_app=None)
 
 ``viewname`` can be a :ref:`URL pattern name <naming-url-patterns>` or the
-callable view object. For example, given the following ``url``::
+callable view object used in the URLconf. For example, given the following
+``url``::
 
     from news import views
 
@@ -79,6 +80,26 @@ use for reversing. By default, the root URLconf for the current thread is used.
     Applying further encoding (such as :func:`urllib.parse.quote`) to the output
     of ``reverse()`` may produce undesirable results.
 
+.. admonition:: Reversing class-based views by view object
+
+    The view object can also be the result of calling
+    :meth:`~django.views.generic.base.View.as_view` if the same view object is
+    used in the URLConf. Following the original example, the view object could
+    be defined as:
+
+    .. code-block:: python
+       :caption: ``news/views.py``
+
+        from django.views import View
+
+
+        class ArchiveView(View): ...
+
+
+        archive = ArchiveView.as_view()
+
+    However, remember that namespaced views cannot be reversed by view object.
+
 ``reverse_lazy()``
 ==================
 
diff --git a/tests/urlpatterns_reverse/tests.py b/tests/urlpatterns_reverse/tests.py
index 216545b5f5..91d3f237ec 100644
--- a/tests/urlpatterns_reverse/tests.py
+++ b/tests/urlpatterns_reverse/tests.py
@@ -522,12 +522,12 @@ class URLPatternReverse(SimpleTestCase):
         with self.assertRaisesMessage(NoReverseMatch, msg):
             reverse("places", kwargs={"arg1": 2})
 
-    def test_func_view_from_cbv(self):
+    def test_view_func_from_cbv(self):
         expected = "/hello/world/"
         url = reverse(views.view_func_from_cbv, kwargs={"name": "world"})
         self.assertEqual(url, expected)
 
-    def test_func_view_from_cbv_no_expected_kwarg(self):
+    def test_view_func_from_cbv_no_expected_kwarg(self):
         with self.assertRaises(NoReverseMatch):
             reverse(views.view_func_from_cbv)
 
diff --git a/tests/urlpatterns_reverse/urls.py b/tests/urlpatterns_reverse/urls.py
index 5bf20a3f63..aca2d06ef7 100644
--- a/tests/urlpatterns_reverse/urls.py
+++ b/tests/urlpatterns_reverse/urls.py
@@ -137,6 +137,6 @@ urlpatterns = [
     path("includes/", include(other_patterns)),
     # Security tests
     re_path("(.+)/security/$", empty_view, name="security"),
-    # View function from cbv
+    # View function from cbv.
     path("hello/<slug:name>/", view_func_from_cbv),
 ]
diff --git a/tests/urlpatterns_reverse/views.py b/tests/urlpatterns_reverse/views.py
index aa55917ec0..01dfc1309e 100644
--- a/tests/urlpatterns_reverse/views.py
+++ b/tests/urlpatterns_reverse/views.py
@@ -58,12 +58,12 @@ def bad_view(request, *args, **kwargs):
     raise ValueError("I don't think I'm getting good value for this view")
 
 
-class _HelloView(View):
+class HelloView(View):
     def get(self, request, *args, **kwargs):
         return HttpResponse(f"Hello {self.kwargs['name']}")
 
 
-view_func_from_cbv = _HelloView.as_view()
+view_func_from_cbv = HelloView.as_view()
 
 empty_view_partial = partial(empty_view, template_name="template.html")
 empty_view_nested_partial = partial(