Source code for cwf.views.redirect_address
from django.utils.http import urlencode
import re
regexes = {
'multi_slash' : re.compile('/+')
}
[docs]class RedirectAddress(object):
"""
Helper to determine where to redirect to.
:param request: Object representing current Django request.
:param address: String representing the address to modify into a redirect url
:param relative: If we should be redirecting relative to the current page we're on
:param carry_get: If we should use the GET parameters from the current request in our redirect
:param ignore_get: List of GET parameters that should be ignored if carry_get is True
"""
def __init__(self, request, address, relative=True, carry_get=False, ignore_get=None):
self.request = request
self.address = address
self.relative = relative
self.carry_get = carry_get
self.ignore_get = ignore_get
########################
### USAGE
########################
@property
def modified(self):
"""Returns the result of ``self.modify(unicode(self.address))``"""
return self.modify(unicode(self.address))
[docs] def modify(self, address):
"""
Return a modified version of the address passed in as the redirect url.
Uses the following methods in a pipeline of sorts (in this order):
* :py:meth:`joined_address`
* :py:meth:`strip_multi_slashes`
* :py:meth:`add_get_params`
"""
address = self.joined_address(address)
address = self.strip_multi_slashes(address)
address = self.add_get_params(address)
return address
########################
### GETTERS
########################
@property
def base_url(self):
"""
Get base url from request.state if request has an attached ``state``.
Otherwise, return ``request.META.get('SCRIPT_NAME', '')``
"""
if hasattr(self.request, 'state'):
return self.request.state.base_url
else:
return self.request.META.get('SCRIPT_NAME', '')
@property
def params(self):
"""
Return dictionary of key value for GET params from ``self.request``.
If not ``self.ignore_get`` then just return ``request.GET``
Otherwise, return ``request.GET`` minus any values whose key is in ``self.ignore_get``
"""
if not self.ignore_get:
return self.request.GET
params = {}
for key, val in self.request.GET.items():
if key not in self.ignore_get:
params[key] = val
return params
########################
### UTILITY
########################
[docs] def strip_multi_slashes(self, string):
"""Replace multiple slashes with single slashes in a string"""
return regexes['multi_slash'].sub('/', string)
[docs] def root_url(self, address):
"""Determine if address is a root url (starts with slash)"""
return address[0] == '/'
[docs] def add_get_params(self, address):
"""
If ``self.carry_get`` is False, then just return the address as is.
Otherwise, urlencode the result of :py:attr:`params` and
return a string that joins address and the parameters.
"""
if not self.carry_get:
return address
params = urlencode(self.params)
return "%s?%s" % (address, params)
[docs] def joined_address(self, address):
"""
If address is a :py:meth:`root_url`, then :py:meth:`join <url_join>` the address with base_url.
Otherwise, if ``self.relative``, then :py:meth:`join <url_join>` the address with ``self.request.path``
If the address is not a root url and ``self.relative`` is False, then return as is
"""
if self.root_url(address):
address = self.url_join(self.base_url, address)
elif self.relative:
address = self.url_join(self.request.path, address)
return address
[docs] def url_join(self, a, b):
"""Helper to join two urls such that there is only one ``/`` between them."""
if not a or not b:
return '%s%s' % (a, b)
elif b[0] == '/' or a[-1] == '/':
return '%s%s' % (a, b)
else:
return '%s/%s' % (a, b)