summaryrefslogtreecommitdiff
path: root/docs
diff options
context:
space:
mode:
Diffstat (limited to 'docs')
-rw-r--r--docs/ref/contrib/admin/actions.txt3
-rw-r--r--docs/ref/contrib/admin/index.txt21
-rw-r--r--docs/ref/models/options.txt16
-rw-r--r--docs/releases/2.1.txt43
-rw-r--r--docs/topics/auth/default.txt4
5 files changed, 78 insertions, 9 deletions
diff --git a/docs/ref/contrib/admin/actions.txt b/docs/ref/contrib/admin/actions.txt
index 0eb6de5b11..88fcd60751 100644
--- a/docs/ref/contrib/admin/actions.txt
+++ b/docs/ref/contrib/admin/actions.txt
@@ -340,6 +340,9 @@ Conditionally enabling or disabling actions
Finally, you can conditionally enable or disable actions on a per-request
(and hence per-user basis) by overriding :meth:`ModelAdmin.get_actions`.
+ This doesn't return any actions if the user doesn't have the "change"
+ permission for the model.
+
This returns a dictionary of actions allowed. The keys are action names, and
the values are ``(function, name, short_description)`` tuples.
diff --git a/docs/ref/contrib/admin/index.txt b/docs/ref/contrib/admin/index.txt
index abaeeb5c22..9b0a7cc8a4 100644
--- a/docs/ref/contrib/admin/index.txt
+++ b/docs/ref/contrib/admin/index.txt
@@ -1623,7 +1623,7 @@ templates used by the :class:`ModelAdmin` views:
a ``list`` or ``tuple`` of :class:`~django.contrib.admin.InlineModelAdmin`
objects, as described below in the :class:`~django.contrib.admin.InlineModelAdmin`
section. For example, the following would return inlines without the default
- filtering based on add, change, and delete permissions::
+ filtering based on add, change, delete, and view permissions::
class MyModelAdmin(admin.ModelAdmin):
inlines = (MyInline,)
@@ -1887,6 +1887,19 @@ templates used by the :class:`ModelAdmin` views:
Override this method to customize the lookups permitted for your
:class:`~django.contrib.admin.ModelAdmin` subclass.
+.. method:: ModelAdmin.has_view_permission(request, obj=None)
+
+ .. versionadded:: 2.1
+
+ Should return ``True`` if viewing ``obj`` is permitted, ``False`` otherwise.
+ If obj is ``None``, should return ``True`` or ``False`` to indicate whether
+ viewing of objects of this type is permitted in general (e.g., ``False``
+ will be interpreted as meaning that the current user is not permitted to
+ view any object of this type).
+
+ The default implementation returns ``True`` if the user has either the
+ "change" or "view" permission.
+
.. method:: ModelAdmin.has_add_permission(request)
Should return ``True`` if adding an object is permitted, ``False``
@@ -1914,7 +1927,8 @@ templates used by the :class:`ModelAdmin` views:
accessing the module's index page is permitted, ``False`` otherwise.
Uses :meth:`User.has_module_perms()
<django.contrib.auth.models.User.has_module_perms>` by default. Overriding
- it does not restrict access to the add, change or delete views,
+ it does not restrict access to the view, add, change, or delete views,
+ :meth:`~ModelAdmin.has_view_permission`,
:meth:`~ModelAdmin.has_add_permission`,
:meth:`~ModelAdmin.has_change_permission`, and
:meth:`~ModelAdmin.has_delete_permission` should be used for that.
@@ -2862,7 +2876,8 @@ Templates can override or extend base admin templates as described in
* ``object_name``: class name of the model
* ``name``: plural name of the model
- * ``perms``: a ``dict`` tracking ``add``, ``change``, and ``delete`` permissions
+ * ``perms``: a ``dict`` tracking ``add``, ``change``, ``delete``, and
+ ``view`` permissions
* ``admin_url``: admin changelist URL for the model
* ``add_url``: admin URL to add a new model instance
diff --git a/docs/ref/models/options.txt b/docs/ref/models/options.txt
index fe51a1a362..51a87fc632 100644
--- a/docs/ref/models/options.txt
+++ b/docs/ref/models/options.txt
@@ -313,7 +313,7 @@ Django quotes column and table names behind the scenes.
.. attribute:: Options.permissions
Extra permissions to enter into the permissions table when creating this object.
- Add, delete and change permissions are automatically created for each
+ Add, change, delete, and view permissions are automatically created for each
model. This example specifies an extra permission, ``can_deliver_pizzas``::
permissions = (("can_deliver_pizzas", "Can deliver pizzas"),)
@@ -326,11 +326,15 @@ Django quotes column and table names behind the scenes.
.. attribute:: Options.default_permissions
- Defaults to ``('add', 'change', 'delete')``. You may customize this list,
- for example, by setting this to an empty list if your app doesn't require
- any of the default permissions. It must be specified on the model before
- the model is created by :djadmin:`migrate` in order to prevent any omitted
- permissions from being created.
+ Defaults to ``('add', 'change', 'delete', 'view')``. You may customize this
+ list, for example, by setting this to an empty list if your app doesn't
+ require any of the default permissions. It must be specified on the model
+ before the model is created by :djadmin:`migrate` in order to prevent any
+ omitted permissions from being created.
+
+ .. versionchanged:: 2.1
+
+ The ``view`` permission was added.
``proxy``
---------
diff --git a/docs/releases/2.1.txt b/docs/releases/2.1.txt
index 083488491c..16641d1923 100644
--- a/docs/releases/2.1.txt
+++ b/docs/releases/2.1.txt
@@ -26,6 +26,21 @@ latest release of each series.
What's new in Django 2.1
========================
+Model "view" permission
+-----------------------
+
+A "view" permission is added to the model :attr:`Meta.default_permissions
+<django.db.models.Options.default_permissions>`. The new permissions will be
+create automatically when running :djadmin:`migrate`.
+
+This allows giving users read-only access to models in the admin.
+:meth:`.ModelAdmin.has_view_permission` is new. The implementation is backwards
+compatible in that there isn't a need to assign the "view" permission to allow
+users who have the "change" permission to edit objects.
+
+There are a couple of :ref:`backwards incompatible considerations
+<view_permission_backwards_incompatible>`.
+
Minor features
--------------
@@ -372,6 +387,34 @@ cross-origin requests. If you rely on the old behavior, set the
:setting:`SESSION_COOKIE_SAMESITE` and/or :setting:`CSRF_COOKIE_SAMESITE`
setting to ``None``.
+.. _view_permission_backwards_incompatible:
+
+Considerations for the new model "view" permission
+--------------------------------------------------
+
+Custom admin forms need to take the view-only case into account
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+With the new "view" permission, existing custom admin forms may raise errors
+when a user doesn't have the change permission because the form might access
+nonexistent fields. Fix this by overriding :meth:`.ModelAdmin.get_form` and
+checking if the user has the "change" permissions and returning the default
+form if not::
+
+ class MyAdmin(admin.ModelAdmin):
+ def get_form(self, request, obj=None, **kwargs):
+ if not self.has_change_permission(request, obj):
+ return super().get_form(request, obj, **kwargs)
+ return CustomForm
+
+New default view permission could allow unwanted access to admin views
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+If you have a custom permission with a codename of the form
+``can_view_<modelname>``, the new view permission handling in the admin will
+allow view access to the changelist and detail pages for those models. If this
+is unwanted, you must change your custom permission codename.
+
Miscellaneous
-------------
diff --git a/docs/topics/auth/default.txt b/docs/topics/auth/default.txt
index 9f864c64d7..94a8fc592f 100644
--- a/docs/topics/auth/default.txt
+++ b/docs/topics/auth/default.txt
@@ -158,6 +158,8 @@ code.
The Django admin site uses permissions as follows:
+* Access to view objects is limited to users with the "view" or "change"
+ permission for that type of object.
* Access to view the "add" form and add an object is limited to users with
the "add" permission for that type of object.
* Access to view the change list, view the "change" form and change an
@@ -168,6 +170,7 @@ The Django admin site uses permissions as follows:
Permissions can be set not only per type of object, but also per specific
object instance. By using the
+:meth:`~django.contrib.admin.ModelAdmin.has_view_permission`,
:meth:`~django.contrib.admin.ModelAdmin.has_add_permission`,
:meth:`~django.contrib.admin.ModelAdmin.has_change_permission` and
:meth:`~django.contrib.admin.ModelAdmin.has_delete_permission` methods provided
@@ -213,6 +216,7 @@ to test for basic permissions you should use:
* add: ``user.has_perm('foo.add_bar')``
* change: ``user.has_perm('foo.change_bar')``
* delete: ``user.has_perm('foo.delete_bar')``
+* view: ``user.has_perm('foo.view_bar')``
The :class:`~django.contrib.auth.models.Permission` model is rarely accessed
directly.