2

Reading the docs lead me to understand that the default permission system in Django is tied to models, which is understandable since it was created for the admin interface.

What does this mean for views? Would the model that's connected to the permission just be kind of not used if I'm only using the permission for views?

Here's to making this question a bit more specific. My goal is to limit a view to one specific group of users.

  1. Create a ContentType:
    content_type = ContentType.objects.get(app_label='myapp', model='SomeModel')

  2. Create a Permission:
    permission = Permission.objects.create(codename='can_view_this', name='Can Access this View', content_type=content_type)

  3. Create a Group:
    group = Group.objects.get_or_create(name='some_group')

  4. Add a permission to the group:
    group.permissions.add(permission)

  5. Add a user to the group:
    group.user_set.add(User.objects.get(id=1))

  6. Test for the permission:
    @user_passes_test(lambda u: u.has_perm('myapp.can_view_this'))
    def some_view(request):

So going back to step #1, notice how I had to assign a model in order to create a ContentType, and I had to create a ContentType because creating a Permission entry requires a ContentType.

So the question is, once again, is that SomeModel being used at all in this scenario? I'm not even sure what exactly which model to assign a view-specific permission, doesn't make any sense.

Hopefully the question makes sense.

reedvoid
  • 1,203
  • 3
  • 18
  • 34

1 Answers1

0

In your scenario above, SomeModel is not being used directly in the view code posted in step six. However, if def some_view were to be fully written, you would find yourself working with SomeModel to query (i.e. view) objects.

@user_passes_test(lambda u: u.has_perm('myapp.can_view_this'))
def some_view(request, template_name='some_template.html'):
    queryset = SomeModel.objects.filter(foo='bar')

    return render(request, template_name, {'queryset': queryset})

In other views you'd find yourself deleting objects:

@user_passes_test(lambda u: u.has_perm('myapp.delete_somemodel'))
def some_delete_view(request, pk, template_name='some_template.html'):
    object = SomeModel.objects.get(pk=pk)
    object.delete()

    return render(request, template_name, {})

There is nothing implicitly using django model permissions in your example, it is up to you.

A Django model by default comes with three permissions: add, change, delete. You can add custom permissions like you did above, or to save some time, specify them on the Model's Meta class.

Scott Woodall
  • 10,456
  • 6
  • 39
  • 37
  • 1
    You claim "permissions are associated with database models because all app interactions do ultimately depend on database interactions", but that's not true. There are plenty of other questions on SO about this concept (e.g. [this one](https://stackoverflow.com/questions/13932774/how-can-i-use-django-permissions-without-defining-a-content-type-or-model)), proposing solutions to creating permissions that are not associated with db models. People come up with these because permissions are not inherently tied to models. This answer should be deprecated (and, IMO, django should make this optional). – Zach Siegel Apr 21 '22 at 21:35