Using Manipulators can be rather cumbersome. Here is a class to simplify the process.

from django import forms
from django.core import validators

class Manipulator(forms.Manipulator):
    default = {}
    done = False
    def __bool__(self):
        return self.done
    def get_data(self, request):
        return request.POST
    def get_form(self, data, errors):
        return forms.FormWrapper(self, data, errors)
    def process(self, request):
        data = self.get_data(request)
        if data:
            new_data = data.copy()
            errors = self.get_validation_errors(new_data)
            if not errors:
                self.done = True
                return self.complete(request, new_data)                
            errors = {}
            new_data = self.default
        self.form = self.get_form(new_data, errors)
        return self.form

    def complete(self, request, data):

Now to use: you should subclass it and fill in the necessary methods ("__init__" and "complete"), and provide fields:

class PollEdit(Manipulator):
    # Provide the fields.
    fields = (
        forms.TextField("title", maxlength=32, is_required=True),
        forms.TextField("question", maxlength=128, is_required=True),

    def __init__(self, poll):
        # We could also provide our fields here, which is usefull if you have
        # custom validators that you need to reference off of "self."

        # Save a reference to our poll.
        self.poll = poll

        # Set our default dictionary to match our poll object.
        # That way the data populating the fields will match our current poll.
        self.default = poll.__dict__
    def complete(self, request, data):
        # This is executed after the user submits valid data.

        # Set the poll's title to the user-submited 'title' in our data.
        self.poll.title = data['title']

        # Same with 'question'
        self.poll.question = data['question']

        # Don't forget to save.

Usage of the final Manipulator is quite simple:

def edit_poll(request, id):
    poll = get_object_or_404(Poll, pk=id)  # Get our poll object.
    manipulator = PollEdit(poll)    # Create the manipulator.
    manipulator.process(request)    # Process the request.
    if (manipulator.form):          # Should we render the form?
         return render_to_response('polls/edit_form', {'form': manipulator.form})
    else:                           # Otherwise, redirect to the poll view page.
         return HttpResponseRedirect("/polls/%d" %

Here's a custom Add Manipulator. Here we can sub-class the first manipulator, so that the fields are the same:

class PollAdd(PollEdit):        
    def __init__(self):
        # Set our default values.
        self.default = {'title': "Unnamed", 'question': 'Insert your question here.'}
    def complete(self, request, data):
        # Create a new poll with our data.
        poll = polls.Poll(title=data['title'], question=data['question'])
        # It'd be nice to be able to get the poll back.
        return poll

And here's the add usage:

def add_poll(request):
    manipulator = PollAdd()             # Create the manipulator
    poll = manipulator.process(request) # Process the request
    if (manipulator.form):              # Should we render the form?
         return render_to_response('polls/new_form', {'form': manipulator.form})
    else:                               # Otherwise, redirect to the poll view page.
         return HttpResponseRedirect("/polls/%d" %


Sometimes Trac annoys the hell out of me. Use the bottom attachment there. I can't fix this error.

Last modified 17 years ago Last modified on 08/24/06 16:13:40

Attachments (2)

Download all attachments as: .zip

Back to Top