0

Simply put, I am trying to test a view name, captured from a URL parameter, within one of my view functions to see if it is valid. If not, to redirect to another page.

For example, take this url...

www.site.com/users/?ref=view_name

Then in my view

    ref = request.GET.get('ref', None)
    return redirect(ref) if ref else redirect('users')

The problem is, of course, that if a user alters the ref parameter, it will kick back a 404. I was hoping to be able to test if ref=home is a valid view and return it, if not then redirect to another view.

I have been messing with Django's resolve and reverse but I am not getting the results I was looking for.

I also tried to use a try/finally in all sorts of ways mixed in with resolve and reverse. Yeah, dumb...I know.

try:
     if ref:
          return redirect(resolve(ref))
finally:        
     return redirect('user')

I have searched for almost two hours to try to fund a succinct way to do this.

Any help would be appreciated!

VIDesignz
  • 4,703
  • 3
  • 25
  • 37
  • Instead of accepting a "view name", why don't you accept an actual URL? It will need to be URL encoded, of course, but this is pretty common, for example in a login flow to determine where to redirect after successful authentication. – Code-Apprentice Jan 24 '22 at 22:05
  • If you insist on using view names here, then `reverse()` is the correct function to use, not `resolve()`. – Code-Apprentice Jan 24 '22 at 22:07
  • 1
    @Code-Apprentice My thought was to use view names as any url changes won't effect existing code. – VIDesignz Jan 24 '22 at 22:09
  • Please post your solution in the section below for answers, not as part of your question. – Code-Apprentice Jan 24 '22 at 22:39

2 Answers2

1

The problem is that you are passing a view name to resolve() which requires a URL path. To protect against 404, you need to first reverse() the view name to get a path. Then you can use that path with resolve() to check if the path exists.

Code-Apprentice
  • 81,660
  • 23
  • 145
  • 268
1

Working Solution This was actually very simple after guidance from @Code-Apprentice

A couple Imports first off

from django.urls.resolvers import NoReverseMatch
from django.urls import reverse

Then to get the ref parameter and validate is as a legit view name I did the following

# get ref parameter
ref = request.GET.get('ref', None)

if ref:
    try:
        # redirect to ref view name if valid
        return redirect(reverse(ref))
    except NoReverseMatch as e:
        print('No reverse match found')

# redirect to specific view if ref is invalid
return redirect('users')
VIDesignz
  • 4,703
  • 3
  • 25
  • 37