Preben Hesvik
Preben Hesvik

Reputation: 57

how to access current user in django model manager

I am making a CRUD application, and I have the current piece of code in my view:

def dashboard(request):
    template = 'dashboard/index.html'
    form = CustomerForm()      
    if request.user.groups.filter(name__in=['West']).exists():
        customers = Customer.objects.filter(Q(department='630') | Q(department='635')).all()
    elif request.user.groups.filter(name__in=['North']).exists():
        customers = Customer.objects.filter(Q(department='610') | Q(department='615') | Q(department='620')).all()
    elif request.user.groups.filter(name__in=['East']).exists():
        customers = Customer.objects.filter(Q(department='660') | Q(department='655') | Q(department='650')).all()
    elif request.user.groups.filter(name__in=['South']).exists():
        customers = Customer.objects.filter(Q(department='640') | Q(department='645')).all()
    elif request.user.groups.filter(name__in=['North-West']).exists():
        customers = Customer.objects.filter(Q(department='625')).all()
    else:
        customers = Customer.objects.all()

    context = {
        "customers": customers,
        "form": form, 
        }

    return render(request, template, context)

I have separate create, update and delete functions that also need to use the same if-statement. I learned about model-manages and created the following:

class CustomerQueryset(models.query.QuerySet):

    def customer_department_query(self):
        if request.user.groups.filter(name__in=['West']).exists():
            customers = Customer.objects.filter(Q(department='630') | Q(department='635')).all()
        elif request.user.groups.filter(name__in=['North']).exists():
            customers = Customer.objects.filter(Q(department='610') | Q(department='615') | Q(department='620')).all()
        elif request.user.groups.filter(name__in=['East']).exists():
            customers = Customer.objects.filter(Q(department='660') | Q(department='655') | Q(department='650')).all()
        elif request.user.groups.filter(name__in=['South']).exists():
            customers = Customer.objects.filter(Q(department='640') | Q(department='645')).all()
        elif request.user.groups.filter(name__in=['North-West']).exists():
            customers = Customer.objects.filter(Q(department='625')).all()
        else:
            customers = Customer.objects.all()

class CustomerManager(models.Manager):
    def get_queryset(self):
        return CustomerQueryset(self.model, using=self.db)

    def get_customer_group(self):
        return self.get_queryset().customer_department_query()

I then found out that the model-manager can't access the request so I created the following middleware:

class GetUser(object):

    def __init__(self, get_response):
        self.get_response = get_response

    def __call__(self, request):

        user = (request.user)
        request.current_user = user
        user_group = request.user.groups.all()
        print(user)
        print(user_group)
        response = self.get_response(request)

        return response

When I refresh my application the shell prints both the user name and the user group but how do I access this information in the Queryset/Model Manager?? Am I even on the right path or is there a better way to do this?

Any help would be much appreciated.

Upvotes: 0

Views: 2495

Answers (1)

Daniel Roseman
Daniel Roseman

Reputation: 599610

This whole approach is wrong.

There's a reason you can't access the "current user" from the manager, which is that there a plenty of circumstances in which there is no current user - if the code is executed from the shell or offline task, if the user is not logged in, and so on.

A better approach would be to make this a method on the User model itself - if you don't already have a custom user model, you can define a simple proxy model with this added method and set AUTH_USER_MODEL to point to that class. The method can then access self.groups directly.

Note, your code could be made simpler by using __in rather than separate Q objects, and you don't need .all() at the end:

customers = Customer.objects.filter(department__in=['630', '635'])

Upvotes: 7

Related Questions