About this document
This document contains details about the components Django MPTT provides for working with trees using Django's excellent newforms library.
The following custom form is provided in the mptt.forms package.
A form which allows the user to move a given node from one location in its tree to another, with optional restriction of the nodes which are valid target nodes for the move.
The form contains the following fields:
target -- a ModelChoiceField for selecting the target node for the node movement.
Target nodes will be displayed as a single <select> with its size attribute set, so the user can scroll through the target nodes without having to open the dropdown list first. The select's options will show the tree structure of the valid target nodes like so:
Root 1 --- Child 1.1 ------ Child 1.1.1 Root 2 --- Child 2.1 --- Child 2.2
position -- a ChoiceField for selecting the position of the node movement, related to the target node.
Its options correspond to the valid values for the position argument for the move_to method Django MTTP adds to model instances.
Required arguments:
Optional arguments:
If provided, this keyword argument will define the list of nodes which are valid for selection in form. Otherwise, any instance of the same model class as the node being moved will be available for selection, apart from the node itself and any of its descendants.
For example, if you want to restrict the node to moving within its own tree, pass a QuerySet containing everything in the node's tree except itself and its descendants (to prevent invalid moves) and the root node (as a user could choose to make the node a sibling of the root node).
When the form's save() method is called, it will attempt to perform the node movement as specified in the form.
If an invalid move is attempted, an error message will be added to the form's non-field errors (accessible using {{ form.non_field_errors }} in templates) and the associated mptt.exceptions.InvalidMove will be re-raised.
It's recommended that you attempt to catch this error and, if caught, allow your view to to fall through to rendering the form again again, so the error message is displayed to the user.
A sample view which shows basic usage of the form is provided below:
from django.http import HttpResponseRedirect
from django.shortcuts import render_to_response
from faqs.models import Category
from mptt.exceptions import InvalidMove
from mptt.forms import MoveNodeForm
def move_category(request, category_pk):
category = get_object_or_404(Category, pk=category_pk)
if request.method == 'POST':
form = MoveNodeForm(category, request.POST)
if form.is_valid():
try:
category = form.save()
return HttpResponseRedirect(category.get_absolute_url())
except InvalidMove:
pass
else:
form = MoveNodeForm(category)
return render_to_response('faqs/move_category.html', {
'form': form,
'category': category,
'category_tree': Category.tree.all(),
})