Django url routing - include url part for dispatching - python

can i substitute the 2 url routes
urlpatterns = patterns('',
url(r'service/geticons', 'core.service.geticons'),
url(r'service/getnearby', 'core.service.getnearby'),
by a single, more generic, route that routes all requests to the function in the service module with the name of the last url segment?
thinking about something like
url(r'service/#f', 'core.service.#f')
or must i do such dispatch in the service module in django?

Sure, you could collect the path and point it to a view that returns the function.
url(r'service/(?P<function>\w+)/$', 'core.service.function_router')
def function_router(request, function):
return globals()[function](request)
But, it's probably better just to explicitly set the urls.

Related

Fetching a mobile or desktop template using django middleware [duplicate]

I want to write custom template loader for my Django app which looks for a specific folder based on a key that is part of the request.
Let me get into more details to be clear. Assume that I will be getting a key on every request(which I populate using a middleware).
Example: request.key could be 'india' or 'usa' or 'uk'.
I want my template loader to look for the template "templates/<key>/<template.html>". So when I say {% include "home.html" %}, I want the template loader to load "templates/india/home.html" or "templates/usa/home.html" or "templates/uk/home.html" based on the request.
Is there a way to pass the request object to a custom template loader?
I've been searching for the same solution and, after a couple days of searching, decided to use threading.local(). Simply make the request object global for the duration of the HTTP request processing! Commence rotten tomato throwing from the gallery.
Let me explain:
As of Django 1.8 (according to the development version docs) the "dirs" argument for all template finding functions will be deprecated. (ref)
This means that there are no arguments passed into a custom template loader other than the template name being requested and the list of template directories. If you want to access paramters in the request URL (or even the session information) you'll have to "reach out" into some other storage mechanism.
import threading
_local = threading.local()
class CustomMiddleware:
def process_request(self, request):
_local.request = request
def load_template_source(template_name, template_dirs=None):
if _local.request:
# Get the request URL and work your magic here!
pass
In my case it wasn't the request object (directly) I was after but rather what site (I'm developing a SaaS solution) the template should be rendered for.
To find the template to render Django uses the get_template method which only gets the template_name and optional dirs argument. So you cannot really pass the request there.
However, if you customize your render_to_response function to pass along a dirs argument you should be able to do it.
For example (assuming you are using a RequestContext as most people would):
from django import shortcuts
from django.conf import settings
def render_to_response(template_name, dictionary=None, context_instance=None, content_type=None, dirs):
assert context_instance, 'This method requires a `RequestContext` instance to function'
if not dirs:
dirs = []
dirs.append(os.path.join(settings.BASE_TEMPLATE_DIR, context_instance['request'].key)
return shortcuts.render_to_response(template_name, dictionary, context_instance, content_type, dirs)

Django: Getting the page an object is on

Let's say I have a class Foo. I want to know what page a particular instance of Foo will be on: eg: api.myapp.com/foos/?page=25.
Given an object:
Foo.objects.get(id=500), how can I determine what page my instance will be on?
My approach is a little bit different so you can do this,
model_ids = (list(Model.objects.values_list('id', flat=True)))
This will give you the list of the ids. After that,
get_page_number = model_ids.index(obj_id) // per_page_objects + 1
If the obj_id is 500 so the index will be 499
now if per_page_objects are 10 then it will give you page number by calculating (499 // 10 +1 = 50).
This means your object having an id 500 is on the 50th page.
I hope this will work for you.
Django by itself does not predefine which url your model will be accessed through.
The documentation says - "Django lets you design URLs however you want, with no framework limitations".
So the process is rather opposite:
you define the url (look inside urls.py) and associate it with the view to be called for processing:
from django.urls import path
from . import views
urlpatterns = [
path('foos/', views.foo_list),
path('foos/<int:id>/', views.foo_detail),
you should define the views (usually in views.py)
and inside the view you can call any models to fetch data from DB
You can implement your API with additional packages like Django Rest Framework.
It has Routers that allow you to define a set of urls at once. The following will generate URL patterns like '^foos/$' and '^foos/{pk}/$':
you register your url within the router
from rest_framework import routers
router = routers.SimpleRouter()
router.register(r'foos', FooViewSet)
you should implement FooViewSet and make sure your model is used there.

mapping URL arguments in Python Requests redirect

While using the Routes library I want to redirect certain URLs. The documentation says it can be achieved like this:
map.redirect("/legacyapp/archives/{url:.*}", "/archives/{url}")
And I am indeed able to redirect to a URL this way. However I am unable to map/parse the URL arguments from the request to the redirect. My code looks like this:
app.mapper.redirect( "/repository/status_for_installed_repository{url:.*}", "/api/repositories/check_updates/{url}" )
and if the app is passed this:
curl -L 'FQDN/repository/status_for_installed_repository?owner=qqqqqq&changeset_revision=e5f6ced3e91f&name=asdsadsadas'
it redirects me to
GET /api/repositories/check_updates
but I cannot find a way how to obtain the values of owner name and changeset_revision.
I expect this to be a common use case as generally you do not want to lose arguments when redirecting?
Any help is much appreciated. Thanks.
I ended up implementing it as follows:
def _map_redirects( app ):
"""
Add redirect to the Routes mapper and forward the received query string.
Subsequently when the redirect is triggered in Routes middleware the request
will not even reach the webapp.
"""
def forward_qs(environ, result):
qs_dict = urlparse.parse_qs(environ['QUERY_STRING'])
for qs in qs_dict:
result[ qs ] = qs_dict[ qs ]
return True
app.mapper.redirect( "/repository/status_for_installed_repository", "/api/repositories/check_updates/", _redirect_code="301 Moved Permanently", conditions=dict( function=forward_qs ) )
return app

How to read parameters from request in django

I need to read some parameters being passed in and perform some action in django. How can I do that.
url = 172.15.20.116/request
and server is requesting with below parameters
url = 172.15.20.116/request/1289/
here 1289 is parameter. How to parse it?
To so this you need to capture this in the urls.
You will need to look into the django url dispatcher this page has pretty much everything you need to get started. Take your time, learn and then implement.
Maybe something like:
from django.conf.urls import url
from . import views
urlpatterns = [
url(r'^request/(?P<id>\d+)/$', 'appname.views.my_request_view'),
]
views.py
def my_request_view(request, id):
... # logic goes here

Shared/Global Dictionary in Django Between URLs and Context Processor

At runtime I'm trying to generate a tree of parent-child relationships between views using the urls.py of different apps. I'm trying to accomplish breadcrumbs by allowing this tree to be defined by an extension of the url function that accepts extra arguments for view_name (name to display on page when used on page, like "Home") and parent_view (specifies the immediate parent so you can generate your breadcrumb).
This class is defined in a separate file in its own module utils.breadcrumbs. The class is called BreadCrumbs and I try to define an instance of BreadCrumbs in the same file for import into various files. This is where it breaks I think.
utils/breadcrumbs.py
class BreadCrumbs:
breadcrumbs = {} # This is our tree
def url(self, pattern, view, arguments={}, name=None, view_name=None, parent_view=None):
... Adds node to self.breadcrumbs ...
return url(pattern, view, arguments, name)
bc = BreadCrumbs()
app/urls.py
from utils.breadcrumbs import bc
urlpatterns = patterns('',
bc.url(r'^home/$', 'app.views.home', name='home', view_name='Home'),
bc.url(r'^subpage/$', 'app.views.subpage', view_name='Sub Page', parent_view="app.views.home"),
)
Then I try to access the tree defined in breadcrumbs.bc in a context processor using the view name given through a middleware. When I had all of my url patterns in the core urls.py file instead of in separate apps, it worked fine. Now that I've moved the url patterns to separate files, the tree is empty when I go to call it in my context processor using a from utils.breadcrumbs import bc. Am I using global variables incorrectly here? Is there a more correct method to share a variable between my urls.py and my context processor? I've looked at sessions, but I don't have access to the request in urls.py, correct?
Your help is appreciated in advance.

Categories