marcelo.delta
marcelo.delta

Reputation: 3072

How to redirect url from middleware in Django?

How to redirect url from middleware?

Infinite loop problem.

I intend to redirect the user to a client registration url if the registration has not yet been completed.

def check_user_active(get_response):
    def middleware(request):
        response = get_response(request)

        try:
            print(Cliente.objects.get(usuario_id=request.user.id))
        except Cliente.DoesNotExist:
            return redirect('confirm')


        return response
    return middleware

Upvotes: 7

Views: 10283

Answers (2)

Raydel Miranda
Raydel Miranda

Reputation: 14360

Update

Despite the downvotes, I still do not recommend using middleware for the specific use case of "redirecting if no registration is complete".

It is a bad idea just to execute that logic for every URL in your application. Even if the user does not need registration, for instance, pages like: "About US", "Q&A", "Home", etc ...

Even worst, taking into account that logic involves a database query!

It is a better solution (even if not what the OP is specifically asking for, in the spirit of SO I am obligated to share it) to create a decorator (just like the one for login_required) to be used in the views you want to ensure the user has finished the registration.

def registration_completed(user):
    # Implement your logic to check if registration is completed for the user.
    # This can be done by checking a specific field or condition in the user model
    # For example, if there is a "registration_completed" field in the User model.

    # I will use in the meantime the exact same logic you have in your code.

    try:
        Cliente.objects.get(usuario_id=request.user.id)
    except Cliente.DoesNotExists:
        return False

    return True
    

def registration_required(func):
    @wraps(func)
    def wrapper(request, *args, **kwargs):
        if not registration_completed(request.user):
            return redirect('registration_completion')  # Redirect to registration completion page if registration is not complete
        return func(request, *args, **kwargs)
    return wrapper

Now achieving what you want is as easy as decorating just the views that you need the user is registered for being able to use:

@registration_required
def my_view(request):
    # Your view code here

You should be using a login_required like decorator see Django authentication system for more detail.

Example:

from django.contrib.auth.decorators import login_required

@login_required(login_url="/your/login/view/url/")
def my_view(request):
    ...

Avoid using middlewares for any kind of redirection always you can, according to the docs

Middleware is a framework of hooks into Django’s request/response processing. It’s a light, low-level “plugin” system for globally altering Django’s input or output.

In other words, middlewares are there for processing request and responses, if you redirect to any view, you will (potentially) recursively trigger your middleware.

And, on the other hand ...

In the future, you might want to add a view that can be visited by anonymous users, this middleware will be a problem ...

Upvotes: 2

ruddra
ruddra

Reputation: 51938

Every request to server goes through Middleware. Hence, when you are going to confirm page, the request goes through middleware again. So its better put some condition here so that it ignores confirm url. You can try like this:

def check_user_active(get_response):
    def middleware(request):
        response = get_response(request)
        if not request.path == "confirm":
            try:
                print(Cliente.objects.get(usuario_id=request.user.id))
            except Cliente.DoesNotExist:
                return redirect('confirm')
        return response
    return middleware

Upvotes: 9

Related Questions