Home > Back-end >  How to access the request in models.py, django
How to access the request in models.py, django

Time:11-09

@property
def get_maca(self, request):
    if  request.user.name == "example":
       return self

I want to do something like this. If the user name is example return that object.

How to access the request like this?

CodePudding user response:

The standard way is to pass the request, or in your case just the user object, from the view/router all the way down to the models.

This gets very quickly out of hand in a larger project, so my approach is to use thread local to save some of the request context that I like to have available across the whole project. The thread local storage will keep data available inside a single thread, without it being accessible from other threads - great if you're gonna run the Django app on a production server.

Start with the local storage:

from threading import local
_active_user = local()

def activate_user(user):
    if not user:
        return

    _active_user.value = user

def deactivate_user():
    if hasattr(_active_user, "value"):
        del _active_user.value

def get_user():
    """Returns `(is_anonymous, user)` ."""
    active_user = getattr(_active_user, "value", None)
    if active_user and active_user is not AnonymousUser:
        try:
            return False, active_user
        except AttributeError:
            pass

    return True, None

Now that's all good, you can use this manually. Calling activate_user will make you be able to call get_user in any place in your project. However, this is error prone - if you forget to call deactivate_user, the user object will still be available to the next coming request.

The rest of the answer is to show how to make things automatic.

Let's first make a middleware to clean up by calling deactivate_user after every single request.

class ThreadCleanupMiddleware:
    def __init__(self, get_response):
        self.get_response = get_response
        # One-time configuration and initialization.

    def __call__(self, request):
        # Executed for each request before
        # the view (and later middleware) are called.

        response = self.get_response(request)

        # Executed for each request/response after
        # the view is called.
        deactivate_user()

        return response

Add a path to the ThreadCleanupMiddleware to the end of your settings.MIDDLEWARE list.

Finish up with a view mixin that activates the user automatically (that's for class based views; if you're using functional views, it would be a decorator instead):

class ContextViewSetMixin:

    def initial(self, request, *args, **kwargs):
        super().initial(request, *args, **kwargs)
        if request.user.is_authenticated:
            activate_user(request.user)

class ContextModelViewSet(ContextViewSetMixin, viewsets.ModelViewSet):
    pass

CodePudding user response:

def form_valid(self):
        self.request.user == "example"
        return super().form_valid()
  • Related