Changing Django's ROOT_URLCONF - python

We are building a multi tenant website, and some tenants want different URLs and such. No big deal, and this is something we already have fixed by making multiple urls.py which can serve as ROOT_URLCONF. When it comes to a request, we simply use our middleware which sets request.urlconf. So far, so good.
But we are also running Celery for a bunch of nightly tasks, and one of those is sending out emails. Here we don't have a request (obviously), so we can't use that to switch the ROOT_URLCONF that way. But changing django.conf.settings.ROOT_URLCONF doesn't work either (which is kinda logical). Is there any way to switch the URLConf that's being used "mid-process"?
It isn't really an option to run multiple Celery instances, each with their own settings because not all objects can be efficiently linked to the tenant they belong to (the views are different, we start with a User which knows it's tenant).

You can use django.core.urlresolvers.set_urlconf:
from django.core.urlresolvers import set_urlconf
set_urlconf('module.path.urls')
That's what django.core.handlers.base.BaseHandler.get_response uses to set up the resolver for the current request.

Related

Add Django endpoint that doesn't require database connection

I have a typical Django project that uses PostgreSQL as it's database backend. I need to set up a specific endpoint (/status/) that works even when the connection to the database is lost. The actual code is very simple (just returns the response directly without touching the DB) but when the DB is down I still get OperationalError when calling this endpoint. This is because I use some pieces of middleware that attempt to contact the database, e.g. session middleware and auth middleware. Is there any way to implement such /status/ endpoint? I could theoretically implement this as a piece of middleware and put it before any other middleware but that seems as kind of hack.
Up to my knowledge no.
If some Middlewares requires a database and you enabled them then they will be used for each request.
I did not read about a way of conditionally executing middlewares depending on the request's url.
So up to my knowledge a normal djangoview will not be able to handle such a status page.
The only solution, that I can imagine is your suggestion to implement a middleware, that is handled first, shortcuts all the other middlewares and returns the result.

Disable sessions in Django

My site serves pages that are almost static and there are no users with logins etc.
I want to completely disable sessions for performance reasons (so django won't access the DB to get the session on every request).
I removed django.contrib.sessions from INSTALLED_APPS, is there anything else I need to do?
You should locate articles how to set up sessions in django and remove everything from settings.py according to such article. Here is it:
Although this should already be setup and working correctly, it’s
nevertheless good practice to learn which Django modules provide which
functionality. In the case of sessions, Django provides middleware
that implements session functionality.
To check that everything is in order, open your Django project’s
settings.py file. Within the file, locate the MIDDLEWARE_CLASSES
tuple. You should find the
django.contrib.sessions.middleware.SessionMiddleware module listed as
a string in the tuple - if you don’t, add it to the tuple now. It is
the SessionMiddleware middleware which enables the creation of unique
sessionid cookies.
The SessionMiddleware is designed to work flexibly with different ways
to store session information. There are many approaches that can be
taken - you could store everything in a file, in a database, or even
in a cache. The most straightforward approach is to use the
django.contrib.sessions application to store session information in a
Django model/database (specifically, the model
django.contrib.sessions.models.Session). To use this approach, you’ll
also need to make sure that django.contrib.sessions is in the
INSTALLED_APPS tuple of your Django project’s settings.py file. If you
add the application now, you’ll need to synchronise your database
using the python manage.py syncdb command to add the new tables to
your database.
So it seems that you should remove middleware too. Maybe it's not necessary, but if you're using static application, then you it's not that bad to remove everything according to the sessions.

Django Performance, url.py evaluation and cache

I have developed project with django. Now facing few problem with optimizations. I have created/used around 53 small applications. Each applications have their local url.py file with their defined urls.
Now there is a main project url.py. this url.py file define urls and include every application local url.py.
Now Each time when user hit any url, Main url.py file is called, which itself call each of the every single url.py then return view for user to hit.
My Question is very simple that how we can force urls.py to be loaded at once and serve urls directly from cache without evaluating every single url.py on every user hit?
Test configurations:
Django 1.5
python 2.7
Server django test server "runserver"
Deployment Configuration:
Django 1.5
python 2.7
Server apache22 with modwisgi
this is how django processes the HttpRequest https://docs.djangoproject.com/en/dev/topics/http/urls/#how-django-processes-a-request
the first 3 steps are:
Django determines the root URLconf module to use. Ordinarily, this
is the value of the ROOT_URLCONF setting, but if the incoming
HttpRequest object has an attribute called urlconf (set by
middleware request processing), its value will be used in place of
the ROOT_URLCONF setting.
Django loads that Python module and looks for the variable
urlpatterns. This should be a Python list of django.conf.urls.url()
instances.
Django runs through each URL pattern, in order, and stops at the
first one that matches the requested URL.
for your purpose you would need to write your own middleware between 2 and 3 which first looks for a pattern in cache, if it doesnot find, it should go on with step 3.
But I dont think you need this. I would go for caching views which is much heavier than urls.

How does a generic Python library manage settings?

I have an existing Django app. Part of it is specific to a Django web app of ours, but another part does a lot of complicated computation, and it may be useful to more of our products. I am busy splitting off this more generic part into a library that does not depend on Django.
The Django app has a few settings -- for instance, it needs to know the location of certain data files. In Django I find that location as the MYAPP_DATA_DIR setting in settings.py, and I use django-appconf to set defaults for such settings.
What's the most common way to handle settings for generic Python libraries? Should I have a configure() function that can be called to set up the library, look in environment variables, something else?

What is an "app" in Django?

According to the documentation:
An app is a Web application that does
something -- e.g., a weblog system, a
database of public records or a simple
poll app. A project is a collection of
configuration and apps for a
particular Web site. A project can
contain multiple apps. An app can be
in multiple projects.
However, what are other examples of what makes an "app"?
What makes an app (for us) is one thing:
An App Is The Unit Of Reuse
If we might want to split it off to use somewhere else, it's an app.
If it has a reusable data model, it's an app. User Profiles: App. Customers: App. Customer Statistical History (this is hard to explain without providing too many details): App. Reporting: App. Actuarial Analysis: App. Vendor API's for data gathering: App.
If it is unique and will never be reused (i.e., customer specific) it's an app that depends on other apps. Data Loads are customer specific. Each is an app that builds on an existing pair of apps (Batch Uploads, and Statistical History)
Django apps are bundles of reusable functionality. When starting off it's easy to just use one custom app for your project, but the "Django way" is to break it up into separate apps that each only do one thing. You can take a look at django.contrib for examples of really well made reusable apps.
A recent example of mine: a client needed a way to import CSV data into the Django models. The easiest way would be to just add a model with a FileField and write a quick parser for the specific format of what they are uploading. That would work fine until the format changed and I had to go make the parser match. But this is a commonly repeated task (importing data) and unrelated to the existing app (managing that data) so I broke it out on its own. This pluggable app can import data for any active model. Now the next time a client needs import functionality I just add this code to installed_apps and run syncdb.
It's a judgement call when to break out an app onto its own, but the rule of thumb for me is if I'm likely to do something again I'll take the extra time to make it a generic app. That means I've created some tiny apps (some just contain a template tag), but it's little overhead for the future gains.
User management could very well be an app, if you are not going to use Django's built in user framework.
It has user interfaces and defined models for stored data, and it is really separate from the Blog or the Wiki application (although the information will be shared).
As long as both applications are in the same 'project' they should use the same settings for the DB. You should be able to by just making sure the proper models are imported where you are trying to use them.
See this link for a little more information.

Categories

Resources