Adventures in Django
From Some Wiki
Contents |
About this page
I am building a site with Django. As I come across various tips that I find handy, I'll post them here, both as reminders for myself and as possible aides to others following the same path.
Edit multiple objects with a form
Turns out it's simpler than you'd think to edit multiple objects using ModelForms - in short, you just create your ModelForms, and stick them into the same HTML form in the template, with one submit button, and then the ModelForms will automagically pick out their elements. Here's a nice link with an example:
http://collingrady.wordpress.com/2008/02/18/editing-multiple-objects-in-django-with-newforms/
Set custom queryset for choice field
To set the choices on a form's ModelChoiceField dynamically, you have to override the Form's init, have it take an extra argument for the queryset you want to use, and stick it into the field. Here's some example code:
class PeriodForm(forms.ModelForm):
world = forms.ModelChoiceField(queryset = World.objects.none())
def __init__(self, *args, **kwargs):
'''Accepts an extra argument, queryset, which sets the world selection choices.'''
try:
queryset = kwargs['queryset']
del kwargs['queryset']
except KeyError:
queryset = World.objects.none()
super(PeriodForm, self).__init__(*args, **kwargs)
self.fields["world"].queryset = queryset
class Meta:
model = Period
The default queryset is set to an empty queryset - we can't just leave it out, because queryset is a required argument. When instantiating the Form, pass it an extra keyword argument of the form "queryset=some_actual_queryset". If it is missing, queryset will be null, and the ModelChoiceField will have zero choices - otherwise the field's choices will be the objects in the queryset you passed to the form.
Push out a "site temporarily unavailable due to maintenance" message
There is an existing django-maintenance middleware for this. I chose to go with a simpler middleware of my own making, in part based on this thread. Here's the code.
from django.conf import settings
from django.http import HttpResponseRedirect
import re
MAINTENANCE_MODE = getattr(settings, 'MAINTENANCE_MODE', False)
MAINTENANCE_PATH = getattr(settings, 'MAINTENANCE_PATH', '/maintenance/')
class MaintenanceMiddleware(object):
def process_request(self, request):
if not MAINTENANCE_MODE:
return None
# Allow acess if the user doing the request is logged in and a
# staff member.
if hasattr(request, 'user') and request.user.is_staff:
return None
# Allow staff members to log in to the admin
# assuming all admin stuff is under /admin
if hasattr(request, 'path') and (re.match(r'/admin', request.path) or re.match(r'^'+MAINTENANCE_PATH+'$', request.path)):
return None
return HttpResponseRedirect(MAINTENANCE_PATH)
In settings.py for the project, add settings for MAINTENANCE_MODE (defaults to False) and MAINTENANCE_PATH (defaults to '/maintenance/'). Also don't forget to append this middleware to the MIDDLEWARE_CLASSES variable in settings.py (make sure it is after the authentication middleware, so that the user checks work).
If you want to bring the site down for maintenance, set the MAINTENANCE_MODE variable to true in settings.py. Note that this will still allow logged in staff members to operate the site, and will still allow users to access the admin and log in - all other users will be redirected to /maintenance/ (or whatever you set that to), where you can place a view/template of your choice.
Comments
Feel free to leave your comments in the discussion page.
