Welcome to django-route’s documentation!¶
Installation¶
Use pip to install from PyPI:
pip install django-route
Add django_route
to your settings.py file:
INSTALLED_APPS = (
...
'django_route',
...
)
Run migrations using:
python manage.py migrate django_route
Getting Started¶
You can define your routing configuration from the django admin panel. For the requests to actually route you need the enable routing.
There are two ways in which you can enable routing.
- Decorator
- Middleware
Decorator¶
If you want to limit routing to specific views, add the django_route.decorators.enable_routing
decorator to those views.:
from django_route.decorators import enable_routing
@enable_routing
def view(request, *args, **kwargs):
...
Middleware¶
If you wish to enable routing for all the urls, add RoutingRequestMiddleware
to your middleware settings.:
MIDDLEWARE_CLASSES = [
...
'django_route.middlewares.RoutingRequestMiddleware',
...
]
django-route’s models¶
Router¶
-
class
django_route.models.
Router
(id, code, source, rank, action, condition, description, is_active)¶ Parameters: - code (SlugField) – Code name for the router. Can be used as variable value inside append_params using {route_code}.
- source (CharField) – Source path
- rank (PositiveSmallIntegerField) – Lower the value higher is it’s preference
- action (CharField) – Path to be followed from source to destination. One of 301/302/proxy
- condition (TextField) – Condition for routing decision
- description (TextField) – Description for router
- is_active (BooleanField) – Active
Destination¶
-
class
django_route.models.
Destination
(id, weight, url, router, carry_params, append_params, is_active)¶ Parameters: - weight (PositiveSmallIntegerField) – Higher the value higher is it’s preference
- url (CharField) – Url
- router_id (ForeignKey) – Router
- carry_params (BooleanField) – Carry forward url params
- append_params (CharField) – Params to be appended
- is_active (BooleanField) – Active
Routing execution¶
Following is the pseudo code for the routing execution model:
if routing is not enabled for the request (no middleware/no decorator)
do nothing
if there is no entry of request.path_info in Router.source which is active
do nothing
if there are multiple entries, order by their rank (ascending order)
for each router
if there are no active destinations
continue with the loop
if the condition is met then break the loop else continue
if the for loop did not break
do nothing
pick a random destination w.r.t their weightage
route to the destination based on the action defined
Settings¶
ENABLE_PROXY_ROUTING¶
default: False
Will enable proxy routing if set to True.
Note
read caveats before enabling this setting.
ROUTING_CACHE¶
default: False
Will cache the routers and corresponding destinations using lru_cache if set to True.
Caveats¶
Proxy Routing¶
You need to enable proxy
setting by explicitly setting ENABLE_PROXY_ROUTING = True
.
Reason:
Since the values passed to wsgi.input and wsgi.errors in request environ are io or socket streams, they cannot be deepcopied. So, we end up passing same streams to essentially two different requests. Network data cannot be seeked and cannot be read outside of its content length. So, we have to pass the same stream to the proxy handler also. The issue is that we cannot read multiple times from wsgi.input. Either it will raise exception or gives empty data or in the worst case deadlock.
Note
Proper care has been taken to prevent these issues. Still there might an issue which I might have overlooked.
Hence the proxy feature is disabled by default.
Warning
YOU HAVE BEEN WARNED!!!
Randomization¶
Routing does not use any custom cookies to tie the outcome to the user. It rather relies on the session key in deriving the outcome of the destinations.
No matter how many times user visits the source path, destination will always be the same.
Note
Destination for a user might change if
- Session key changes. (Session key changes during login/logout)
- New active destination has been added to the router or weightage of the active destinations has been changed. Since the sample space has been changed, outcome might vary.
Contributing¶
- Fork it!
- Create your feature branch:
git checkout -b my-new-feature
- Commit your changes:
git commit -am 'Add some feature'
- Push to the branch:
git push origin my-new-feature
- Submit a pull request :D
Issues¶
Use the GitHub issue tracker for django-route to submit bugs, issues, and feature requests.