Background
==========
Two years ago, Malcolm Tredinnick put up an excellent post about doing dynamic Django forms. There have been several excellent write-ups on it since - Google is your friend.
One year ago, I attempted to make a dynamic Formset - see [this snippet](http://www.djangosnippets.org/snippets/1290/). Malcolm posted a cleaner solution two weeks later, and I liked his solution better. Some time after that happened, his site tanked.
I'm re-posting my snippet using his technique, so that everyone can see how it is done. Credit to goes to Malcolm - I'm just the messenger. If his site ever comes back up , check out his complex formset post [here](http://www.pointy-stick.com/blog/2009/01/23/advanced-formset-usage-django/).
I'll use Malcolm's example code, with as few changes as possible to use a formset. The models and form don't change, and the template is almost identical.
I won't reproduce all of Malcolm's code - I'm just show the form setup. There are no models here - you'll have to use your imagination for Quiz, Question, and Answer models. He did some fancy validation as well - I'm not going to here.
Problem
=======
Build a formset based on dynamically created forms.
Solution
========
The core idea in this code is found in the `_construct_form` method. Typically, this is where a formset makes new forms - it handles indexing them so that everything is nice and unique. We can take advantage of this by overriding the method and inserting a `kwarg` that will be passed on to our form class, then calling the parent `_contruct_form` method to let it finish doing everything else for us. This is what Malcolm, a core Django developer, knows about, and I, a random Django user, typically do not.
Code
====
This pattern greatly simplifies building formsets dynamically, and it really only requires a few bits of knowledge.
1. If we `pop()` special arguments out of `kwargs` dictionaries, we then can pass the remaining `kwargs` along to parent methods and let them do the rest of the setup for us. See code tricks #1 and #3.
2. If we have a form and need to add dynamic fields that we didn't declare the usual way, we can just add them to the `self.fields` dictionary. See code trick #2.
3. If we need to add forms dynamically to a formset, we can use the `self.extra` variable to specify how many we want, based on the length of a custom queryset. See code trick #4.
4. If we want to pass some special arguments to a form that will be part of a formset when it is constructed, we can add them to the `kwargs` dict in `_construct_form`, taking advantage of the `index` variable to track which object from our queryset we wanted. See code trick #5.
A general AntiSpamForm using some tricks to prevent spam based on current [django.contrib.comments.forms](http://code.djangoproject.com/browser/django/trunk/django/contrib/comments/forms.py). It uses a timestamp, a security hash and a honeypot field. See [AntiSpamModelForm](http://www.djangosnippets.org/snippets/1856/) too.
**NOTE: I now have a better implementation of this (nicer api, less signal wrangling) available [on PyPI here](https://pypi.python.org/pypi/django-exclusivebooleanfield)**
Sometimes you want to be able to make one (and only one) row in your model 'featured' or 'the default one'
If you have some kind of parent model you could have a ForeignKey on the parent to hold that info, but that won't always be the case - eg you may have no parent, or multiple parent models.
With the exclusive_boolean_fields() helper you can do it with or without a parent model and it possibly makes the admin interface a bit simpler.
This template tag provides an easy way to render objects in your template, even if you don't know ahead of time what type they are.
For example, if you've got a search page with a result list comprised of objects from various models, you can simply loop through them and render them using the tag. The tag will choose the best template and render the object for you.
The tag's docstring has all the details. I hope you find this as useful as I have. Questions, comments, complaints welcome.
Django Pagination Template Tag that allows unlimited customization to the current Django Pagination.
Automatically creates template variables that can be used to display the pagination in any format that you can desire such as
Previous 1 2 3 [ 4 ] 5 6 7 Next
First Previous 12 14 15 16 17 [ 18 ] 19 20 22 25 Next Last
Showing 25 of 80 Results
First Page 23 27 30 33 [ 36 ] 38 41 44 50 Next Last
This snippet provides a @group_required decorator. You can pass in multiple groups, for example:
@group_required('admins','editors')
def myview(request, id):
...
Note: the decorator is based on the snippet [here](http://fragmentsofcode.wordpress.com/2008/12/08/django-group_required-decorator/) but extends it checking first that the user is logged in before testing for group membership - [user_passes_test](http://docs.djangoproject.com/en/dev/topics/auth/#django.contrib.auth.decorators.user_passes_test) does not check for this by default.
It is important to check that the user is first logged in, as anonymous users trigger an AttributeError when the groups filter is executed.
A generic admin action to export selected objects as csv file. The csv file contains a first line with header information build from the models field names followed by the actual data rows.
Access is limited to staff users.
Requires django-1.1.
**Usage:**
Add the code to your project, e.g. a file called actions.py in the project root.
Register the action in your apps admin.py:
from myproject.actions import export_as_csv
class MyAdmin(admin.ModelAdmin):
actions = [export_as_csv]
This is a username field that matches (and slightly tightens) the constraints on usernames in Django's `User` model.
Most people use RegexField, which is totally fine -- but it can't provide the fine-grained and user friendly messages that come from this field.
Here is a way to get a drop down list from a queryset, with a list of "featured" items appearing at the top (from another queryset). This can be used for long select boxes which have a subset of commonly used values. The empty label is used as a separator and values can appear in both the featured set and the full set (it's more usable if they are in both).
For example a country drop down list with 5 featured countries might look like this:
Andorra
Australia
Kazakhstan
Singapore
Turkey
------------
Afghanistan
Albania
Algeria
American Samoa
Andorra
Angola
(hundreds more)
To use this, define your form field like this:
country = FeaturedModelChoiceField(queryset=Country.objects.all(),
featured_queryset=Country.objects.featured())
Put this in an __init__.py somewhere that will be executed on initialization and all errors will be printed out to stderr. Useful for debugging Facebook apps, javascript calls, etc.
Sometimes you need to filter foreignkey choices in admin interface, to objects created by user or meeting some other condition. In django 1.0 there is no formfield_for_foreignkey method in ModelAdmin class so we have to make a workaround. Here is the solution I have found to be the easiest for me.
My take on digg-like pagination.
Save the code as 'templatetags/pagination_nav.py' in one of your apps.
It relies on a 'pagination_nav.html' template. Here is a base template:
{% if pages %}
<div class="bottom-pagination-nav">
{% if previous_url %}<a href="{{ previous_url }}">{% else %}<span>{% endif %}« Previous{% if previous_url %}</a>{% else %}</span>{% endif %}
{% for group in pages %}
{% for page in group %}
{% if page.current %}<span>{{ page.number }}</span>{% else %}<a href="{{ page.url }}">{{ page.number }}</a>{% endif %}
{% endfor %}
{% if not forloop.last %}<span>...</span>{% endif %}
{% endfor %}
{% if next_url %}<a href="{{ next_url }}">{% else %}<span>{% endif %}Next »{% if next_url %}</a>{% else %}</span>{% endif %}
</div>
{% endif %}
A simple jQuery javascript that collapses all stacked inline rows for better handling of large inline fieldsets.
It also adds "Show"/"Hide"-buttons for showing/hiding each row, which could be customized and styled using css.
**Usage (see below for example):**
Include the javascript on your admin page, together with jQuery, and it'll automatically affect all stacked inlines.
**Developed for:**
* jQuery 1.3.2
* Django trunk (tested in Django v1.0.2)
* (Might work with other versions with or without adjustments, but not tested)
**Use example: **
*admin.py:*
class DateInline(admin.StackedInline):
model = Date
extra = 10
class EventAdmin(admin.ModelAdmin):
inlines = [DateInline]
class Media:
js = ['js/jquery-1.3.2.min.js', 'js/collapsed_stacked_inlines.js',]
admin.site.register(Event, EventAdmin)
**Mobilize your Django site**
This is the code for a Django middleware class to allow you to easily mobilize your Django site. It makes use of [Wapple.net](http://wapple.net)'s Web services to provide device profiling and markup generation.
Using this middleware plugin, you can deliver your site to both mobile and web browsers using the same domain and exactly the same url structure and Python views. The WAPL markup language allows you to render sites to every single mobile device without worrying about the individual devices yourself.
**Requirements**
1. The [SUDS](https://fedorahosted.org/suds/) Python SOAP client.
2. A WAPL dev key. Sign up for one at [http://wapl.info](http://wapl.info)
3. The Django sessions framework must be enabled. See [http://docs.djangoproject.com/en/dev/topics/http/sessions/](http://docs.djangoproject.com/en/dev/topics/http/sessions/) for how to install.
**How To Use**
1. Save the code above as 'wapl_middleware.py' in the root of your project.
2. Replace 'YOUR-DEV-KEY-HERE' with your WAPL dev key.
3. In your project's 'settings'py', add the following to the bottom of your 'MIDDLEWARE_CLASSES' setting:
`'myapp.wapl_middleware.WAPLMiddleware',`
4. For each line in your 'TEMPLATE_DIRS' setting, create a new folder under that folder called 'wapl' e.g. for 'myapp/templates/', you would create the folder under 'myapp/templates/wapl/'.
5. For each template used in your application, write a WAPL version and save it in the corresponding 'wapl' directory. See [http://wapl.info/docs/chapter/Developing-with-WAPL/](the WAPL docs) for information about the WAPL markup language.
6. Django template inheritance and includes can be used as normal, so I recommend creating a 'base.html' like this one.
`<?xml version="1.0" encoding="UTF-8" ?>
<wapl xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="http://wapl.wapple.net/wapl.xsd">
<head>
{% block wapl_head %}{% endblock %}
</head>
<layout>
{% block wapl_layout %}{% endblock %}
</layout>
</wapl>`
7. View your site from a mobile device, and you should see a nice mobile version.
**How It Works**
1. When a request is made, the middleware checks to see if a session variable is held telling us if the device is mobile or not.
2. If we don't already know, it calls the WAPL web services to check. It then stores this in the session for subsequent requests.
3. If the device is a mobile device, it appends 'wapl' to each line in your 'TEMPLATE_DIRS' setting. Your view code will work exactly the same as normal, and the 'wapl' templates will be used whenever a response is rendered.
4. When a response is about to be rendered, the middleware checks to see if the device is a mobile one.
5. If it is mobile, and the response about to be sent has a status code of 200 (OK), it sends the WAPL markup to the WAPL web service to generate the correct markup for that device.
6. Otherwise, it outputs the response unmodified.
**Tips**
1. Don't try to migrate your whole site to mobile - design for mobile and consider the user's goals on a handset.
2. If leaving sections out, don't just leave the wapl view out. Include one that says 'This page is not available on mobile'. This will make sure none of your external links are dead on the mobile version.
3. For full developer reference, information and schemas, see [http://wapl.info](WAPL.info).
You're looking at the most-bookmarked snippets on the site; if you'd like to help useful snippets show up here, sign up for an account and you'll get your own bookmarks list.