Django: dynamically mapping views in urls.py - python

I have a viewsdirectory containing say a hundred view files. How can i make my urls.py transfer control to these view files without putting in an "intermediate handler" as described here (answered 3 years back).
Basically- is there a cleaner way for redirecting control to views in django?

The view function returns an HTML page that includes the current date and time. To display this view at a particular URL, you’ll need to create a URLconf; see URL dispatcher for instructions.
https://docs.djangoproject.com/en/1.7/topics/http/urls/
For redirecting you should use the Django redirect shortcut function
from django.shortcuts import redirect
def my_view(request):
...
return redirect('some-view-name', foo='bar')
https://docs.djangoproject.com/en/1.7/topics/http/shortcuts/#redirect

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)

Render different templates for ListView

I have a ListView with some good functionality that i want to use from another app. The way i did it was using get_template_names.
def get_template_names(self):
referer = self.request.META['HTTP_REFERER']
if "/mwo/order/" in referer:
return ['invent/use_part.html']
return ['invent/part_list.html']
Which i access from two different apps:
path('inventory/', PartListView.as_view(), name='partlist'),
...
path('mwo/order/<int:pk>/add_part/', PartListView.as_view(),
name='add_part'),
But it causes a bug if i use a direct link to 1st url from navbar and not from another app. Now i'm new to django and i'm pretty sure there should be a better way for this. What can i use instead of request referrer to render different template for ListView when i access it from another view.
You can specify the template_name in the .as_view:
path('inventory/', PartListView.as_view(template_name='invent/part_list.html'), name='partlist'),
# …
path('mwo/order/<int:pk>/add_part/', PartListView.as_view(template_name='invent/use_part.html'), name='add_part'),
Then of course you should remove the get_template_names from the method, since otherwise you will override that behaviour.

Django: need Dynamic login redirect using info from database redirect after login, using built-in login

After I login, I need to redirect to another page while adding URL parameters to the URL of the next page. I get the value of these parameters after the user is authenticated because they need to be accessed from the user database table. I heard about using the next parameter but I don't know how I would use it since I need to access the database table and I can't do that from urls.py. This is my url.py line for login right now:
url(r'^$',auth_views.login, name='login',kwargs={
'authentication_form':loginPlaceHolderForm,
}),
I'm not really sure what other info you need so just ask for it in the comments and I'll be sure to add it.
Also I'm using Django 1.11
EDIT:
For more clarification: What I want is something like this /colors?team=blue
And let's say the team can be red, blue or green and you get this value from the team column in the given row that you get when the user logs in.
You could try to override djangos class-based view LoginView.
In views.py
from django.contrib.auth.views import LoginView
class MyLoginView(LoginView):
authentication_form = loginPlaceHolderForm
def get_redirect_url(self):
print(self.request.user)
# get data for user here
user_data_query_string = ''
url = '{}?{}'.format(
reverse('app:some-name')
user_data_query_string)
return url
In urls.py
url(r'^$', MyLoginView.as_view(), name='login'),
See also this question about adding GET querystring parameters to djangos HttpRedirect.

How do I redirect visitors to login page?

I have the following url handler in my main Django project urls.py:
url(r'^$', 'core.views.generic.index')
Instead of landing on the index page as above, I want users to land on the login page.
I have another urls.py in an app called core that sends visitors to the login page:
url(r'^/login$', private.MeLogin.as_view())
How can I send all the people visiting url(r'^$', ...) in my main app to private.MeLogin.as_view() in my core app?
EDIT:
I have tried the following,
def index(request):
return HttpResponseRedirect('/#/login')
but I get that this page has a redirect loop
The way to solve that be using a decorator, in this case login_required.
Django documentation
from django.contrib.auth.decorators import login_required
#login_required
def index(request):
index view code in here
What this will do is redirect you to your login view.
As mention in the Documentation
login_required() does the following:
If the user isn’t logged in, redirect to settings.LOGIN_URL, passing the current absolute path in the query string.
If the user is logged in, execute the view normally. The view code is free to assume the user is logged in.
You can also customize your decorator check the documentation for more information.
To login required, you must use a decorator indicating that:
from django.contrib.auth.decorators import login_required
#login_required
def index(request):
return render(request,'home.html')
In any view that the login is required, just use it.

Django Admin Custom Pages and Features

I'm (new to) working in Django and would like to create two features that do not rely upon models/database tables. The basis of this app is as a web-based wrapper to a Python application.
The features are:
I would like to be able to load a ConfigObj text file into a page and edit it's configuration prior to saving again.
I would like to be able to call command line python/bash scripts and display their output on a page - like exec in PHP.
At the moment I'm working on simple custom admin pages without model as described here:
Django admin, section without "model"?
Would this be the right direction to go in? I'm not sure proxy tables apply as the features I desire have nothing to do with any data.
So far I have looked at is it possible to create a custom admin view without a model behind it and a few other links. At the moment I have:
main/urls.py
url(r'^admin/weectrl', include('weectrl.urls')),
which links with weectrl/urls.py
from weectrl import views
urlpatterns = patterns('',
(r'^admin/weectrl/manage/$', weectrl_manage_view),
(r'^admin/weectrl/config/$', weectrl_config_view),
)
which points to weectrl/views.py
def weectrl_manage_view(request):
r = render_to_response('admin/weectrl/manage.html', context, RequestContext(request))
return HttpResponse(r)
def weectrl_config_view(request):
r = render_to_response('admin/weectrl/config.html', context, RequestContext(request))
return HttpResponse(r)
The current error message is name 'weectrl_manage_view' is not defined
Ok, found something that works.
In the main url.py
url(r'^admin/weectrl/', include('weectrl.urls')),
In app/urls.py
urlpatterns = patterns('',
url(r'^config/$', views.config, name='config'),
url(r'^manage/$', views.manage, name='manage'),
)
and in app/views.py
def config(request):
context = ""
return render(request, 'weectrl/config.html', context)
def manage(request):
context = ""
return render(request, 'weectrl/manage.html', context)
html files are in app/templates/app/...

Categories