简体   繁体   中英

django-rules: trouble making it work as expected in templates

Disclaimer: I'm new to django and django-rules.

I have defined my model. The Model has 2 foreign keys to the user table. Creator and supervisor. Instances should be changeable/updated by staff, creator or supervisor.

I have defined predicates for is_creator and is_supervisor and made a rule:

@rules.predicate
def is_creator(user, mymodel):
    return mymodel.creator == user

@rules.predicate
def is_supervisor(user, mymodel):
    return mymodel.supervisor == user

can_edit = is_supervisor | is_creator | rules.is_staff

And in the models meta class I added:

rules_permissions = {           
    'change': can_edit
}

In my view I then want to show an edit button that links to edit form based on these permissions.

{% block content %}
{% has_perm 'mymodel.change_mymodel' user instance as can_edit %}
{% if can_edit %}
<button type="button" class="btn btn-warning"><h6>Edit</h6></button>
{% endif %}
{% endblock %}

When I log in as superuser, the button is displayed as expected. When I user a test user that should be able to edit a specific instance, the button is not displayed at all. So there are certain checks made but not as expected.

I have a second similar functionality for the index page. Showing only actions the users has the privilege for. Again, the superuser sees it all but the test user does not.

In this case I have below predicate which is used as "add" permission" on a different Model:

@rules.predicate
def can_add_xyz(user):
    return rules.is_staff | rules.is_group_member("Add_XYZ")

It seems in both cases all the checks besides the is_staff seem to fail. What am I doing wrong?

There are two issues going on. First RTFM and do it correctly:

In my template I used has_perm entity_name.add_entity_name instead of using as properly described in the documentation has_perm myapp.add_entity_name .

After fixing that the predicates now actually got called and I could debug them. And there a bigger problem revealed itself. I was able to fix it but don't like the fix.

The predicate:

@rules.predicate
def is_creator(user, mymodel):
    return mymodel.creator == user

The issue is that in the template I'm checking this permission, mymodel is a related entity generated by a nested django-rest-framework serializer. This means that the instance used in the template that is then submitted to this predicate is not a mymodel instance but an OrderedDict and hence I get an Exception like OrderedDict has no attribute 'creator'.

An additional issue is that creator isn't directly a Django auth_user but an OneToOne extended User. So mymodel.creator == user would never be true.

@rules.predicate
def is_creator(user, mymodel):
    #if called from template as related entity,
    #mymodel is an OrderedDict from a serializer
    if isinstance(mymodel, collections.OrderedDict):        
        return mymodel["creator"] == user.userprofile.pk
    return mymodel.creator == user.userprofile

This fixes the issue and now the right things are displayed but I'm not entirely happy with this (type checking). So any advice to make this better is still welcome.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM