Tuesday, October 7, 2014

Re: Show a model on the admin list index page

-----BEGIN PGP SIGNATURE-----
Comment: GPGTools - https://gpgtools.org

iQIcBAEBCgAGBQJUM6v2AAoJEB267zEX1rwQggkP/iHNjePEU8LgW1a9OR+3PPKE
/g9tj1+8gj5gcmkNTL4mwq+K//SKbdjoSGtu89RVqIG82hWxHveMS2aQxSHkWayx
lSuaN7ooraL4cyI5dGaC2tzPDO08SYNp31DHeLvyCIaVC7r4/7K2BdlQN8iR6/DB
tqNG+4GHAcd+44e+gGamQDA/xQLGaOVGxtgiqxHEVil3LOs/P4OZKOvKt6kHtXnY
p3SNR/yWjpdKq2H9INj3GtAiofVB/aB9gbCHza/9atL2dM4bBqWIUrkWjOG9HYGe
jd8pf+pcDksqlNWNokH6yMC3I1prGgEzGeXRfyU7nnorLQ3BvyMk0+0Cc6mudwz3
k3Guzuv2nDZdtk8vefzEYJI8tfE/1yLIFvF/kcIKhakEJviwQ0aLx8oTR7zy8mp/
md21yRY+EEM0IewPV3cZ1UVjJoqzlvgZMeos/C9ah2R3r1WaLtgqn5AeAw8qSF1c
sbJmlB+YvEw+4+VVFlhiW6eixmeim2INDq3p3JNzofP0phsjMUf2cxoiAnK+0kpY
MBwc584tkwOn2g7ML2CcPY7E2fS4k+EmwM1llnJCPEbK5E2rJWRPJpNwwrUAmHAj
zxnJk/uVQDjsKG4GESfncKQG9m67Hb98C951gViQiVW4e4RYm6OuLttpugGckkU8
Sr5wuNnPct6lYFFLeQKr
=rtxq
-----END PGP SIGNATURE-----
Hi Andrea,

I answer below in between lines.

On 07 Oct 2014, at 08:53, Andrea <andrea.ge85@gmail.com> wrote:

Let's suppose I have a Foo app with a Bar model with a owner field. I want a user to be able to edit all the instances for which obj.owner == request.user.

The model appears correctly in the admin panel for superusers and for users for which I have explicitly assigned the permission change_bar or add_bar, as explained here:

Assuming you have an application with an app_label foo and a model named Bar, 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')

How can I show the model Bar in the admin index list without explicitly assigning foo.change_bar or foo.add_bar to the user?



You can't. The admin interface of Django assumes that when a user has access to the administrative interface of an App-Model it's not to act as a mere passive consumer with read-only access but rather as an active admin over the content (add, change, delete). An administrator who does only inspect or supervise the content doesn't fit in the sort of administrator that the Django administration app allows. It's like allowing an administrator who actually does not administer. 

So far I tried the following, expecting the Bar model to appear in the index list page, but it didn't work.

class BarAdmin(admin.ModelAdmin):      def get_queryset(self, request):          qs = super(BarAdmin, self).get_queryset(request)          if request.user.is_superuser:              return qs                  return qs.filter(owner=request.user)        def has_add_permission(self, request):          return True        def has_change_permission(self, request, obj=None):          if obj is None:              return True          if obj.owner == request.user:              return True          return False        def has_delete_permission(self, request, obj=None):          if obj is None:              return True          if obj.owner == request.user:              return True          return False        def has_module_permission(self, request):          return True

Accessing the link admin/foo/bar/ works correctly for every user and returns the list of Bar instances for which obj.owner == request.user. admin/foo/bar/add allows the user to add a new object correctly. These links are although not displayed in the admin index page: which is the function that triggers the appearance of the model in the index page? admin/foo/ returns 403 Forbidden.


Uhm… this looks strange to me. So you don't want to provide the user with add/change/delete permissions but you are faking them. 

The Bar model doesn't appear in the App index list page because the view function in charge first verifies whether the user has any of the add/change/delete permissions granted for such App, and given that your user doesn't have them the App Foo is not listed. In other words, you would have to override the index admin view too (in django.contrib.admin.sites.py), which I don't recommend. Think that by overriding the way permissions are handled in the admin interface you might end up giving change access to regular users that shouldn't have access at all. 

My recommendation here is to create your own supervising interface for Foo, with its own URLs, to provide the readonly functionality your target users needs. Those users might not probably fall in the category of admins. I'm thinking in maybe managers who need to see what's going on but doesn't have to have write access.

Does this answer your questions?

I'm using Django 1.7

Thanks,

Andrea



Cheers,
Daniel

No comments:

Post a Comment