Skip to content

Instantly share code, notes, and snippets.

@pipermerriam
Last active December 10, 2015 14:19
Show Gist options
  • Save pipermerriam/4446905 to your computer and use it in GitHub Desktop.
Save pipermerriam/4446905 to your computer and use it in GitHub Desktop.
from django.utils.http import is_safe_url
from django.core.urlresolvers import reverse
from django.utils.safestring import mark_safe
class WithNextUrlMixin(object):
"""
This view will use whatever value was submitted as `next` as the success
url, as long as the url resolves correctly.
"""
def get_success_url(self):
return self.get_next_url() or super(WithNextUrlMixin, self).get_success_url()
def get_next_url(self):
next = self.request.REQUEST.get('next')
if next and is_safe_url(next):
return next
def get_context_data(self, **kwargs):
kwargs = super(WithNextUrlMixin, self).get_context_data(**kwargs)
next = self.get_next_url()
if next:
kwargs['next'] = next
kwargs['next_input'] = mark_safe('<input type="hidden" name="next" value="{0}">'.format(next))
return kwargs
@classmethod
def as_view(cls, *args, **kwargs):
"""
Wraps View.as_view to add a with_next function on the view object.
with_next will return the reverse of the current view with the query
string for the next URL appended.
"""
view = super(WithNextUrlMixin, cls).as_view(*args, **kwargs)
def with_next(next_url, args=None, kwargs=None):
return '{0}?{1}'.format(
reverse(view, args=args, kwargs=kwargs),
urllib.urlencode({'next': next_url}),
)
view.with_next = with_next
return view
class LoginView(WithNextUrlMixin, ...):
...
login = LoginView.as_view()
class NeedsLoginView(...):
def get(self, *args, **kwargs):
if not self.request.user.is_authenticated():
return redirect(login.with_next(self.request.path))
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment