0

My question is not the same with View permissions in Django because that one explains how to deal with the issue in Django 2.1 and higher which has a concept of "view" permission while I am working with Django 1.1. which does not.

Django 1.11

I have a group users who should have only read-only access to everything on the site. No restrictions on fields, models, and actial data, only what they can do with it (read-only). I know about possible implementations that suggest doing it "field-by-field" (or "make all fields read-only") and "model-by-model" solution. I am curios if there is a way to do it cleaner, on user group level, or at least on user level.

My views.py so far is default:

from django.shortcuts import render
from django.contrib.auth.decorators import login_required

@login_required 
def index(request):
    """View function for home page of site."""


    # Render the HTML template index.html with the data in the context variable
    return render(request, 'home.html')

Ideally, I'd like to be able to do this with a fixture. Currently in the fixture, I have my groups defined like this:

{
    "model": "auth.group",
    "fields": {
        "name": "some_group",
        "permissions": [
            [
                "add_somemodel",
                "myproject",
                "somemodel"
            ],
            [
                "change_somemodel",
                "myproject",
                "somemodel"
            ],
            [
                "delete_somemodel",
                "myproject",
                "somemodel"
            ]

         ]
       }
}

In Django 2.2 I can do

{
    "model": "auth.group",
    "fields": {
        "name": "some_group",
        "permissions": [
            [
                "view_somemodel",
                "myproject",
                "somemodel"
            ]  
         ]
       }
}

but in Django 1.11 I have only "add", "delete" and "change" - no "view" option (according to the docs enter link description here). So, is there a way to create a fixture that creates a group that has only read permissions for everything?

SwissNavy
  • 619
  • 1
  • 12
  • 28
  • are you using django-admin – rahul.m Apr 10 '19 at 09:48
  • @c.grey I have `INSTALLED_APPS = [ ... 'django.contrib.admin', .... ]` in my settings.py if that's what you are asking – SwissNavy Apr 10 '19 at 09:53
  • the permissions you show are only used in django-admin. To use them in your own views, you need to explicitly check them anyway. Nothing is stopping you from creating your own permission and checking it using (`has_perm()`) or to just create a special `Group` and check if the user is in that group. Check the [docs](https://docs.djangoproject.com/en/1.11/topics/auth/default/#programmatically-creating-permissions) – dirkgroten Apr 10 '19 at 11:26
  • Possible duplicate of [View permissions in Django](https://stackoverflow.com/questions/23104449/view-permissions-in-django) – Iakovos Belonias Apr 10 '19 at 12:29

2 Answers2

0

In your view you need something like this(Notice that this is an example of how to view a post if you belong to the proper access group):

def post_detail(request, slug=None):
    if not request.user.is_staff or not request.user.is_superuser:
        raise Http404
    instance = get_object_or_404(Post, slug=slug)
    share_string = quote_plus(instance.content)
    context = {
        "title": instance.title,
        "instance": instance,
        "share_string": share_string,
    }
    return render(request, "post_detail.html", context)

Pay attention to:

if not request.user.is_staff or not request.user.is_superuser:
        raise Http404

Here are some link to the docs that will help you:

How to authenticate users

All attributes to django.contrib.auth

Edit: I saw your code now, so what you want to achieve can be done like this

from django.shortcuts import render
from django.contrib.auth.decorators import login_required

@login_required 
def index(request):
    """View function for home page of site."""
    # With that way although a user might be logged in
    # but the user might not have access to see the page
    if not request.user.is_staff or not request.user.is_superuser:
        raise Http404


    # Render the HTML template index.html with the data in the context variable
    return render(request, 'home.html')

That way a user may be logged in, but if it's not staff member or superuser it want have access to the page.

Iakovos Belonias
  • 1,217
  • 9
  • 25
  • Not sure I understand. Where is it setting a specific group (or a user) as having only read permissions? – SwissNavy Apr 10 '19 at 10:05
  • When you creating your models, for each user you can have a field of what he/she is. and then in the view you can have the check logic – Iakovos Belonias Apr 10 '19 at 10:08
  • This page describes exactly what you want https://docs.djangoproject.com/en/2.2/topics/auth/default/ – Iakovos Belonias Apr 10 '19 at 10:11
  • Yes, that's 2.2. But Django 1.11 does not have "view" permission, only add, change and delete - or I am mistaken? – SwissNavy Apr 10 '19 at 10:16
  • I can't understand what you are asking but here is for the version 1.11 I think is exactly the same https://docs.djangoproject.com/en/1.11/topics/auth/default/ . The thing about django is that there is no huge gap between versions. – Iakovos Belonias Apr 10 '19 at 10:20
  • Sorry I probably should have stated that I am trying to achieve that with the fixtures. Updated the post – SwissNavy Apr 10 '19 at 10:33
  • Also: check for is_stuff and is_superuser as you suggest did not disable "Add " button. – SwissNavy Apr 10 '19 at 10:39
  • is_stuff and is_supersuer is an example I gave you. You can use anything you want from https://docs.djangoproject.com/en/1.11/ref/contrib/auth/#django-contrib-auth – Iakovos Belonias Apr 10 '19 at 10:47
  • @SwissNavy this is confusing me: are you talking about django-admin or your own views? ("add model" button is in django admin, but maybe it's something in your own view) – dirkgroten Apr 10 '19 at 11:27
  • @SwissNavy [check this](https://stackoverflow.com/questions/3068843/permission-to-view-but-not-to-change-django) and [this](https://stackoverflow.com/questions/3068843/permission-to-view-but-not-to-change-django) – Iakovos Belonias Apr 10 '19 at 12:31
  • @dirkgroten I was trying to see what's the easiest/cleanest way to configure a group members of which would be able to see all the data in all the models but won't be able to add, edit or create anything anywhere in Django 1.11. I am open to review any implementation, but my first thought was it should be doible with user/group/permissions setup in the DB only because I can do that for "add" and "delete". Apparently it's not the same for "view" in 1.11 – SwissNavy Apr 10 '19 at 13:48
  • No, “add” and “delete” permissions only have a meaning in the admin site. In your own views if you don’t do anything and creat a view to “add” a model, even users who don’t have the “add” permission will be able to create a model instance. Unless you check it explicitly in your view. So what I’m saying is, you have to do the same for “view”, except in addition you have to create a permission for it. – dirkgroten Apr 10 '19 at 14:48
  • @dirkgroten I think I understood the difference you are talking about. Yes, I browse the models and entities in them from the admin. – SwissNavy Apr 10 '19 at 16:44
  • So basically the `index` view has nothing to do with your question? you just want to have "view-only" functionality in django-admin? Then update to Django 2.2. There's no other easy way. – dirkgroten Apr 10 '19 at 16:49
  • @dirkgroten Correct, index view code was in the question just to show that I did not add anything custom yet. Upgrade to 2.2 now is approved and scheduled this year :-). However, for the current setup the solution I came up with works. – SwissNavy Apr 11 '19 at 08:41
0

Thank you everybody for responding. I did not figure out the way to do it with only user/group/permissions config in the db with Django 1.11, maybe it does not exist. Here is what I ended up with (very similar to the first suggestion I hit on SO when I started the research 4 hours ago, with minimal code changes)

  1. Create a fixture for my new group that contains only "change_somemodel" permission and created a user as a member of that group, i.e. no "add_somemodel" and no "delete_somemodel" entries and load it into DB:
[
    {
        "model": "auth.group",
        "fields": {
            "name": "<my_new_group>",
            "permissions": [
                [
                    "change_<somemodel1>",
                    "<myproject>",
                    "<somemodel1>"
                ],

                [
                    "change_<somemodel2>",
                    "<myproject>",
                    "<somemodel2>"
                ]
             ]
    }
,
    {
    "model": "auth.user",
    "fields": {
        "password": "<my_password>",
        "last_login": null,
        "is_superuser": false,
        "username": "<my_username>",
        "first_name": "",
        "last_name": "",
        "email": "",
        "is_staff": true,
        "is_active": true,
        "date_joined": "2019-04-01T14:40:30.249Z",
        "groups": [
            [
                "<my_new_group>"
            ]
        ],
        "user_permissions": []
    }
}
],

This took care of the first part: now when I login as this user I do not have "Add new.." or "Delete" buttons anywhere for any model for my user.

  1. Now, when I load a view for a given instance of some model, I still have the fields editable and I still see "Save", "Save and Add Another" and "Save and Continue" buttons. To take care of this, in admin.py in the superclass from which all my models are subclassed, in its custom def changeform_view I added:
if request.user.groups.filter(name='<my_new_group>'): 
   extra_context['show_save_and_add_another'] = False
   extra_context['show_save_and_continue'] = False
   extra_context['show_save'] = False

This made those 3 "Save" buttons disappear for all the models and made all fields read-only. Now this new user can not add, delete or edit anything for any model yet they can see everything, just as I wanted.

Looks like in the newer Django, starting from 2.1, this can be done even better.

SwissNavy
  • 619
  • 1
  • 12
  • 28