Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Show error message when decorator fails

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)
like image 727
chachan Avatar asked Nov 30 '25 08:11

chachan


1 Answers

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.

like image 53
okm Avatar answered Dec 02 '25 03:12

okm



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!