3

The decorator is working fine but I would like to display an error message (I'd like to use messages framework) if the user doesn't belong to any of the required groups. Here's the decorator:

def group_required(*group_names):
    """Requires user membership in at least one of the groups passed in."""
    def in_groups(user):
        if user.is_authenticated():
            if bool(user.groups.filter(name__in=group_names)) or user.is_superuser:
                return True
        return False
    return user_passes_test(in_groups)

I call it using something like:

@require_http_methods(['GET'])    
@group_required('supervisor')
def home_view(request):
    return render(request, 'home.html')

I tried using this snippet to use messages framework (since this requires the request object) but it realized that messages framework middleware didn't appear installed inside the decorator.

I'm willing to change whatever it takes :)

Update:

What I'm looking for:

def group_required(request, *group_names):
    """Requires user membership in at least one of the groups passed in."""
    def in_groups(user):
        if user.is_authenticated():
            if user.groups.filter(name__in=group_names).exists() or user.is_superuser:
                return True
            else:
                # I'm getting:
                # You cannot add messages without installing django.contrib.messages.middleware.MessageMiddleware
                messages.add_message(request, messages.ERROR, 'Group is not allowed')
        return False
    return user_passes_test(in_groups, request)
chachan
  • 2,382
  • 1
  • 26
  • 41
  • I just logged what request contains and it's not the request object. I think my problems is passing the request object to the decorator – chachan May 05 '13 at 14:27

1 Answers1

1

I don't think you really need threadlocals in this use case. And normally when threadlocals seems to be the only way to go in a Django app, there could be some mis-structured context layers. Comparing w/ the threadlocals, I would rather to duplicate user_passes_test and then modify it to pass request to in_groups (We could not pass request to is_group easily without modifying the code of user_passes_test. Check the question: How to pass Django request object in user_passes_test decorator callable function.) (Maybe a ticket for this?)

Furthermore, bool(user.groups.filter(name__in=group_names)) would caused items to be retrieved to DB adapter and Python instance before deciding the existence, using exists() and thus user.groups.filter(name__in=group_names).exists() to directly return bool result from DB backend is far more efficient here.

Community
  • 1
  • 1
okm
  • 23,575
  • 5
  • 83
  • 90
  • Thanks for answering, I changed the query statement and looks better. Regarding the message issue, I did the replacement but I'm still getting the "You cannot add messages without installing django.contrib.messages.middleware.MessageMiddleware", which I have but I guess this is out of its context, any idea how to make messages framework available in this point? – chachan May 04 '13 at 18:09
  • @chachan Did you override the user_passes_test ? How did you fix the part of getting the request object inside group_required ? – Sandeep Balagopal Jul 11 '17 at 07:09
  • @SandeepBalagopal Sorry, I can't tell at the moment, that was 4 years ago – chachan Jul 11 '17 at 12:25