How to add app to all pages in django? - django

I have an app called lastapp that I would like it to be viewable on all pages. It renders base.html so it's available on all apps. So far I've tried adding it to the urls.py like this:
urlpatterns = patterns('',
(r'^first/$', firstapp, lastapp),
(r'^last/$', lastapp),
)
But when I go to /first/ it gives me the error: Error, 'function' not iterable. It shows fine when going to /last/. If I remove lastapp from the /first/ site in urls.py, then firstapp shows fine also. Is there a special way to do this? Thanks in advance.

What exactly are you trying to do?
All installed applications are available in your project, but the application by it self does not return any data to the template, that's the job of the views which are part of that application.
My guess is that firstapp and lastapp are rather views then apps.
If that is a case, context processors make it possible to always pass certain data to a template.
So, create a context processor out of lastapp and set it in TEMPLATE_CONTEXT_PROCESSORS in settings.py.

I think what you need is probably Middleware.

Related

Mobile templates based on user-agent in django ensuring thread safety

I am developing the mobile version of my website, so thought of using user-agent as the criteria for serving different templates for mobile and web version.
I successfully read the user-agent information from nginx and passed it as header to gunicorn server.
Then I created a middleware which reads this header and changes the templates directory in settings file. This seemed to work initially but then I realized that there is race condition happening as this method is not thread safe. (I should have thought of it before-hand).
So I started thinking of other alternatives. One solution was to overwrite the render method of django to include "dirs" parameter based on request header. But then I found out that the "dirs" parameter is deprecated. Following is the reference link https://docs.djangoproject.com/en/1.9/_modules/django/shortcuts/#render
So even this will not work.
Another solution is to have different template names for mobile and web and load them accordingly. However I don't want to do this and want to keep the templates directory structure exactly same for both web and mobile.
There has to be a way to just overwrite the template directory. This will give me an advantage of falling back on web version of templates if its missing in mobile templates directory.
Any advise on how to achieve this will be helpful.
This is how my templates are organized.
App1
templates
App1
index.html
catalog.html
App2
templates
App2
about.html
And in the project directory(not part of the app folder), there is a mobile templates folder which has the following structure
mobile-templates
App1
index.html
App2
about.html
Thanks
Anurag
Here's how I would organize my templates:
Make two directories inside templates dir - mobile and desktop.
Keep mobile templates in mobile dir and desktop templates in desktop.
This way you won't have to rename the templates.
And here's how I would render them:
Read User-Agent in a middleware.
Set an attribute on request called template_prefix whose value will either be mobile or desktop, depending on the User-Agent. Eg:
def process_request(self, request):
# read user agent and determine if
# request is from mobile or desktop
# ...
if mobile_user_agent:
request.template_prefix = 'mobile'
else:
request.template_prefix = 'desktop'
In your views, use request.template_prefix before template names. Eg:
def home(request):
...
template = request.template_prefix + '/home.html'
return render(request, template)
This will render the templates from either mobile or desktop dirs depending on the value template_prefix attribute.
UPDATE (according to question edit):
Looking at how your templates are organized, I'd do this:
Middleware:
Only set template_prefix for mobile requests.
def process_request(self, request):
if mobile_user_agent:
request.template_prefix = 'mobile-templates'
else:
request.template_prefix = '' # set an empty string
Views:
Use os.path.join; catch TemplateDoesNotExist exception.
import os.path
from django.template.loader import get_template
from django.template.base import TemplateDoesNotExist
def index(request):
try:
template = os.path.join(request.template_prefix, 'App1/index.html')
get_template(template)
except TemplateDoesNotExist:
template = 'App1/index.html'
return render(request, template)
I've tested this and it works. But writing a try...except block in every view seems redundant. If I come up with a better solution, I will update.
It seems it isn't possible to this out of the box right now. If you really want to follow this architecture, you will have to write your own custom loader and also figure out a way to pass the request/indicator to let it know its a mobile request.
It's not too tough to write the loader (just see the Django filesystem loader, if the request is from mobile, loop through all the templates_dirs and add the proper suffix to it, so that you include mobile dirs too).
However the biggest challenge as I see it is being able to pass a dynamic parameter to it (indicating that this is a mobile request). You may store this param in the session or modify the template name before passing it to the custom renderer (The renderer will remove this indicator part and get the template) .

Django reverts to default urls

I'm working with Django 1.6.4 and I've constructed a login system that appears to be working up until the back button is pressed in the browser. The URL giving me fits is http://127.0.0.1:8000/login. Here is my project URLconf:
urlpatterns = patterns('',
(r'', include('apps.mylogin.urls')),
)
(Before any of you Django veterans point out the empty regex pattern :) – I've tried a number of different ones that have been suggested on the interwebs: ('^', '^$'), and even tried moving the app's URLconf into the project's URLconf and all of them seem to yield this error. Of course if you detect shenanigans in this code, feel free to point it out, I like best practices :D)
The URLconf contained in the include is as follows:
urlpatterns = patterns('apps.mylogin.views',
url(r'^login/$', 'login', name='login'),
url(r'^logged_in/$', 'logged_in', name='logged_in'),
)
Let's say I land on the login page and I don't enter any information, I just click submit; the LoginForm class that I've created will (during the clean method) return a raise ValidationError. Everything works as expected: all the appropriate errors are displayed to the user and life is peachy... until I hit the back button. It is at this point I'm presented with a captured 404 page that says it was a GET request sent to http://127.0.0.1:8000/login with the following read out:
Using the URLconf defined in myproject.urls, Django tried these URL patterns, in this order:
^admin/
^account/
The current URL, login/, didn't match any of these.
I'm assuming these URLs are some part of a 'base' set defined by Django; which is well enough and all, but I'm quite curious as to why it appears to have forgot my URLs and suddenly can't find the location I was just at.
Any help would be greatly appreciated and if there is any additional information required please let me know and I'll attempt to edit this question to reflect it.
After yet additional testing and thought on the matter it appears that there is a conflict of caching mechanisms. It appears the conflict is produced when using certain Safari extensions, causing what appeared to be an injection of information; when in reality it was using code from several tutorials that had run before it.
I've arrived at this conclusion by testing Chrome, Firefox and Safari all without any extensions or enhancements beyond their default configuration. It is only when I return to Safari and enable a specific extension (and what is more absurd is that this particular extension does not inhibit my desktop ... it might be likely that there are additional extensions working in conjunction to cause this) that I receive the captured 404 error along with the seemingly injected ^account/.

Changing settings in settings.py via the webpage/template

I have been recently asked to "hack" into django/python and edit a project. I have never programmed in anything as close to these two languages, so I am studying them on the go.
I did my homework and searched through couple of topics
Can I access constants in settings.py from templates in Django?
Django - app to edit the constants in settings.py in admin interface
and then
http://blog.chipx86.com/2008/08/05/django-development-with-djblets-dynamic-site-configuration/
However, since this is not something I programmed, I have been asked to add some features to admin configuration page to be editable from there and enhance some other portions of the website. I also understand that those require restart of django server.
The guy that did this had site_config.py and settings.py . From the live version of the project, only accessible/editable constants were those from site_config.py. I managed to reproduce those this is how a portion of site_config.py looks like.
## SITE #
# Populate default site config values here
SITE_DISPLAY_NAME = 'testing123'
SITE_COMPANY_NAME = 'another123'
Now the question is how would I add a portion from urls.py to the given site_config.py
urlpatterns = patterns('',
# We don't yet have a top-level main view, redirect to AIM app
(r'^$', 'django.views.generic.simple.redirect_to', {'url': '/aim/'}),
This is the portion that I would like to incorporate to the site_config.py. What would I have to do?
If you need more information, please let me know, and I am sorry if this is a newbie question, but I really never worked on anything like this before.
Thank you.

How can I disable /account/register on django-registration?

[Newbie] I tried to disable django-registration by:
1.registration_allowed()
I saw this method on the source registration_allowed() /registration/views but I don't know if it's what I need or how to use it.
Maybe I need a variable on settings.py
2.Commenting the lines
Commenting the /registration/backends/urls.py register urls (only the lines regarding registration)
But this breaks the urls, so any idea?
Thanks!
Registration actually includes a setting for this called REGISTRATION_OPEN. Simply set it to false in your settings.py file and include a registration/registration_closed.html template.
Short solution: you can place a reference to your own view in urls.py ABOVE including registration's urls. So your view will intercept the request, and you can do anything you want (i.e. return redirect somewhere else).
Correct solution: write your own registration backend and templates and remove references to the register view from there.

Django's Satchmo and flatpages issue

I'm having a problem with configuring Flatpages in Satchmo. I've used them before, in a pure django app, but now it just doesn't work, returning 301 http error when I'm trying to enter a flatpage-configured site.
What I've done to configure it:
added the middleware "django.contrib.flatpages.middleware.FlatpageFallbackMiddleware" to MIDDLEWARE_CLASSES as last in the list,
configured example pages in admin module.
Simply what the docs say about flatpages config.
I'm feeling helpless. Don't know how could I debug this issue. Any thoughts on that?
And of course help appreciated.
Thanks to suggestion by Peter I've managed to narrow the problem to my urls.py file, for the satchmo shop.
The urlpatterns has only one entry:
(r'', 'django.views.generic.simple.redirect_to', {'url' : '/shop/'}),
This version does not work and moreover interfere with flatpages. But disabling flatpages from MIDDLEWARE_CLASSES and adding it to urls.py like the snippet below works:
(r'^(?P<url>.*)$', 'django.contrib.flatpages.views.flatpage'),
(r'', 'django.views.generic.simple.redirect_to', {'url' : '/shop/'}),
However next problem is with the redirection from / to /shop/. With the above config it results in infinite loop.
Perhaps you know the reason for that behavior (redirect overriding flatpage) and maybe You could suggest some working solution to this problem or what should be done with requests to /.
It returns 301? That's Page Moved Permanently (HttpResponsePermanentRedirect) and there are no references to that in the flatpages directory so I don't think it's coming from there. In fact there are only about 5 references to HttpResponsePermanentRedirect in all of the standard 1.1.1 release.
Possible approaches:
Comment out the FlatPages middleware and see if the error changes (I'm betting it won't).
Try changing the order of your MIDDLEWARE classes and see if things change.
When presenting a problem like this it's better to get very specific by showing the exact code from applicable portions of settings.py (or whatever) and by giving other things like precise URLs and the urls.py patterns you are trying to match.
Update:
OK, some random thoughts:
The pattern (r'^(?P<url>.*)$', 'django.contrib.flatpages.views.flatpage'), will match anything. Any patterns after it will never be seen.
flatpages doesn't work by being called directly, it does its magic in middleware. It looks for 404 responses (Page Not Found) and then looks to see if that path exists in its table. If so, it calls a view that renders the page, etc. etc. If it doesn't find a match it let's the 404 continue on through middleware processing.
The pattern (r'', 'django.views.generic.simple.redirect_to', {'url' : '/shop/'}), will match anything (I just tested it). If you want to match an empty path, use r('^$', etc.). This is the source of your infinite loop.
If you are new to regular expressions the Django urls.py file can seem like F*cking Magic. I recommend starting very simply and add one rule at a time. Do some quick tests to ensure that the new rule a) matches stuff you want it to match, and b) doesn't match stuff it shouldn't. In particular, make sure that some of the rules that occur later in the file are still reachable. In this case they wouldn't have been which should have raised a red flag.