mirror of
https://github.com/django/django.git
synced 2025-06-05 11:39:13 +00:00
[4.1.x] Fixed #34172 -- Improved ModelAdmin.get_urls example.
Backport of 0036bcdcb65874f63fff8139fe86574fa155eb26 from main
This commit is contained in:
parent
7713370f08
commit
3137174344
@ -1566,7 +1566,8 @@ templates used by the :class:`ModelAdmin` views:
|
|||||||
|
|
||||||
The ``get_urls`` method on a ``ModelAdmin`` returns the URLs to be used for
|
The ``get_urls`` method on a ``ModelAdmin`` returns the URLs to be used for
|
||||||
that ModelAdmin in the same way as a URLconf. Therefore you can extend
|
that ModelAdmin in the same way as a URLconf. Therefore you can extend
|
||||||
them as documented in :doc:`/topics/http/urls`::
|
them as documented in :doc:`/topics/http/urls`, using the
|
||||||
|
``AdminSite.admin_view()`` wrapper on your views::
|
||||||
|
|
||||||
from django.contrib import admin
|
from django.contrib import admin
|
||||||
from django.template.response import TemplateResponse
|
from django.template.response import TemplateResponse
|
||||||
@ -1576,7 +1577,7 @@ templates used by the :class:`ModelAdmin` views:
|
|||||||
def get_urls(self):
|
def get_urls(self):
|
||||||
urls = super().get_urls()
|
urls = super().get_urls()
|
||||||
my_urls = [
|
my_urls = [
|
||||||
path('my_view/', self.my_view),
|
path('my_view/', self.admin_site.admin_view(self.my_view))
|
||||||
]
|
]
|
||||||
return my_urls + urls
|
return my_urls + urls
|
||||||
|
|
||||||
@ -1599,6 +1600,18 @@ templates used by the :class:`ModelAdmin` views:
|
|||||||
...
|
...
|
||||||
{% endblock %}
|
{% endblock %}
|
||||||
|
|
||||||
|
.. note::
|
||||||
|
|
||||||
|
Notice how the ``self.my_view`` function is wrapped in
|
||||||
|
``self.admin_site.admin_view``. This is important, since it ensures two
|
||||||
|
things:
|
||||||
|
|
||||||
|
#. Permission checks are run, ensuring only active staff users can
|
||||||
|
access the view.
|
||||||
|
#. The :func:`django.views.decorators.cache.never_cache` decorator is
|
||||||
|
applied to prevent caching, ensuring the returned information is
|
||||||
|
up-to-date.
|
||||||
|
|
||||||
.. note::
|
.. note::
|
||||||
|
|
||||||
Notice that the custom patterns are included *before* the regular admin
|
Notice that the custom patterns are included *before* the regular admin
|
||||||
@ -1610,36 +1623,6 @@ templates used by the :class:`ModelAdmin` views:
|
|||||||
``/admin/myapp/mymodel/my_view/`` (assuming the admin URLs are included
|
``/admin/myapp/mymodel/my_view/`` (assuming the admin URLs are included
|
||||||
at ``/admin/``.)
|
at ``/admin/``.)
|
||||||
|
|
||||||
However, the ``self.my_view`` function registered above suffers from two
|
|
||||||
problems:
|
|
||||||
|
|
||||||
* It will *not* perform any permission checks, so it will be accessible
|
|
||||||
to the general public.
|
|
||||||
* It will *not* provide any header details to prevent caching. This means
|
|
||||||
if the page retrieves data from the database, and caching middleware is
|
|
||||||
active, the page could show outdated information.
|
|
||||||
|
|
||||||
Since this is usually not what you want, Django provides a convenience
|
|
||||||
wrapper to check permissions and mark the view as non-cacheable. This
|
|
||||||
wrapper is ``AdminSite.admin_view()`` (i.e. ``self.admin_site.admin_view``
|
|
||||||
inside a ``ModelAdmin`` instance); use it like so::
|
|
||||||
|
|
||||||
class MyModelAdmin(admin.ModelAdmin):
|
|
||||||
def get_urls(self):
|
|
||||||
urls = super().get_urls()
|
|
||||||
my_urls = [
|
|
||||||
path('my_view/', self.admin_site.admin_view(self.my_view))
|
|
||||||
]
|
|
||||||
return my_urls + urls
|
|
||||||
|
|
||||||
Notice the wrapped view in the fifth line above::
|
|
||||||
|
|
||||||
path('my_view/', self.admin_site.admin_view(self.my_view))
|
|
||||||
|
|
||||||
This wrapping will protect ``self.my_view`` from unauthorized access and
|
|
||||||
will apply the :func:`django.views.decorators.cache.never_cache` decorator to
|
|
||||||
make sure it is not cached if the cache middleware is active.
|
|
||||||
|
|
||||||
If the page is cacheable, but you still want the permission check to be
|
If the page is cacheable, but you still want the permission check to be
|
||||||
performed, you can pass a ``cacheable=True`` argument to
|
performed, you can pass a ``cacheable=True`` argument to
|
||||||
``AdminSite.admin_view()``::
|
``AdminSite.admin_view()``::
|
||||||
|
Loading…
x
Reference in New Issue
Block a user