public
Description: utilities for implementing a modified pre-order traversal tree in django
Homepage: http://code.google.com/p/django-mptt/
Clone URL: git://github.com/brosner/django-mptt.git
BACKWARDS-INCOMPATIBLE CHANGE - model registration is now handled by 
mptt.register instead of mptt.models.treeify

git-svn-id: http://django-mptt.googlecode.com/svn/trunk@77 
7eea2103-5a42-0410-ac78-6383eb04bdbf
jonathan.buchanan (author)
Fri Jan 11 20:36:57 -0800 2008
commit  f2dd5b43c93789568284341f70b982008a29f101
tree    1276d7f12e04e6979e28ee43653500dd5990c449
parent  d0e86b05e9fc9fc18ffaf9bc153a38533620b940
...
10
11
12
 
 
 
13
14
15
...
97
98
99
100
101
102
 
 
 
 
103
104
105
...
10
11
12
13
14
15
16
17
18
...
100
101
102
 
 
 
103
104
105
106
107
108
109
0
@@ -10,6 +10,9 @@ Trunk Changes
0
 Sat 12th Jan, 2008
0
 ------------------
0
 
0
+* BACKWARDS-INCOMPATIBLE CHANGE - model registration is now handled by
0
+ ``mptt.register`` instead of ``mptt.models.treeify``.
0
+
0
 * An exception is now raised if you call ``treeify`` on the same
0
   ``Model`` class twice.
0
 
0
@@ -97,9 +100,10 @@ Fri 4th Jan, 2008
0
   have to check for this special case - they can be sure they'll never
0
   have to handle a root sibling move when ``move_node`` is being used.
0
 
0
-* Simplified the node movement API - ``move_node()`` is now
0
- ``TreeManager``'s only public means of moving a node, as it can figure
0
- out what to do based on the node and target given.
0
+* BACKWARDS-INCOMPATIBLE CHANGE - Simplified the node movement API -
0
+ ``move_node()`` is now ``TreeManager``'s only public means of moving a
0
+ node, as it can figure out what to do based on the node and target
0
+ given.
0
 
0
   This simplifies implementation somewhat, as the methods which actually
0
   do the moving can trust their caller with the types of nodes which
0
...
16
17
18
19
20
21
 
 
 
22
23
24
...
16
17
18
 
 
 
19
20
21
22
23
24
0
@@ -16,9 +16,9 @@ Since it's not unreasonable to assume a good percentage of the people
0
 who use this application will also be using the ``django.contrib.admin``
0
 application or ``newforms`` forms generated with ``ModelForm`` to edit
0
 their data, and since in these cases only the parent field will be
0
-editable if users have allowed ``mptt.models.treeify`` to create tree
0
-fields for them, it would be nice if Django MPTT automatically took care
0
-of the tree when a ``Model`` instance has its parent changed.
0
+editable if users have allowed ``mptt.register`` to create tree fields
0
+for them, it would be nice if Django MPTT automatically took care of the
0
+tree when a ``Model`` instance has its parent changed.
0
 
0
 When the parent of a tree node is changed, its left, right, level and
0
 tree id may also be updated to keep the integrity of the tree structure
...
14
15
16
17
18
 
 
19
20
21
22
23
 
24
25
26
 
 
27
28
29
30
31
32
33
 
 
 
 
 
34
35
36
...
84
85
86
87
 
88
89
90
91
92
93
 
94
95
96
97
98
99
 
100
101
102
...
220
221
222
223
 
224
225
226
...
14
15
16
 
 
17
18
19
20
21
22
 
23
24
 
 
25
26
27
28
 
 
 
 
 
29
30
31
32
33
34
35
36
...
84
85
86
 
87
88
89
90
91
92
 
93
94
95
96
97
98
 
99
100
101
102
...
220
221
222
 
223
224
225
226
0
@@ -14,23 +14,23 @@ Models and Managers
0
 Setting up a Django model for MPTT
0
 ==================================
0
 
0
-The ``mptt.models`` module contains a ``treeify`` function, which users
0
-can call to set a Django model up for MPTT. This function takes as its
0
+The ``mptt`` module contains a ``register`` function, which users can
0
+call to set a Django model up for MPTT. This function takes as its
0
 arguments the model class itself and, optionally, attribute names for
0
 the set of fields which are required in order to manage the database
0
 table for the model as a tree.
0
 
0
-.. admonition:: ``treeify`` and ``syncdb``
0
+.. admonition:: ``mptt.register`` and ``syncdb``
0
 
0
- As discussed further below, the ``treeify`` function will add new
0
- fields to your models if certain required tree fields are not
0
+ As discussed further below, the ``mptt.register`` function will add
0
+ new fields to your models if certain required tree fields are not
0
    present.
0
 
0
- As such, you must have the call to ``treeify`` in place **before**
0
- you use Django's ``syncdb`` management command to create tables for
0
- any models you wish to set up for MPTT, otherwise you will have to
0
- recreate those tables so the appropriate tree columns are in place in
0
- the database.
0
+ As such, unless you are manually setting up all required tree fields
0
+ in your models, you must have the call to ``mptt.register`` in place
0
+ **before** you use Django's ``syncdb`` management command to create
0
+ tables. Otherwise, you will have to recreate tables so the
0
+ appropriate tree columns are in place in the database.
0
 
0
 The following argument is required:
0
 
0
@@ -84,19 +84,19 @@ class, see the technical details documentation.
0
 
0
 .. _`minimal example usage`:
0
 
0
-A mimimal example usage of ``treeify`` is given below, where the
0
+A mimimal example usage of ``mptt.register`` is given below, where the
0
 model being set up for MPTT is suitable for use with the default
0
 arguments::
0
 
0
    from django.db import models
0
 
0
- from mptt.models import treeify
0
+ import mptt
0
 
0
    class Genre(models.Model):
0
        name = models.CharField(max_length=50, unique=True)
0
        parent = models.ForeignKey('self', null=True, blank=True, related_name='children')
0
 
0
- treeify(Genre)
0
+ mptt.register(Genre)
0
 
0
 
0
 Model instance methods added by Django MPTT
0
@@ -220,7 +220,7 @@ The ``TreeManager`` custom manager
0
 A custom manager, ``TreeManager`` is also added to your Django models
0
 when you set them up for MPTT - the attribute this manager can be
0
 accessed through is specified by the ``tree_manager_attr`` argument to
0
-``treeify``.
0
+``mptt.register``.
0
 
0
 Any ``QuerySet`` created with this manager will be ordered based on the
0
 tree structure, with root nodes appearing in tree id order and and their
...
92
93
94
95
96
 
 
97
98
99
...
92
93
94
 
 
95
96
97
98
99
0
@@ -92,8 +92,8 @@ Dynamic field creation vs. explicitly defining MPTT fields
0
 ==========================================================
0
 
0
 Model classes which do not have field names which clash with the default
0
-arguments to the ``treeify`` function need not contain any details about
0
-MPTT fields at all in their class definition.
0
+arguments to the ``mptt.register`` function need not contain any details
0
+about MPTT fields at all in their class definition.
0
 
0
 One of the goals of this application is that authors should not have to
0
 worry about setting up or using MPTT fields directly in order to reap
...
 
 
 
 
 
 
 
 
 
1
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
...
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
0
@@ -1 +1,72 @@
0
+from django.db.models import signals as model_signals
0
+from django.db.models import FieldDoesNotExist, PositiveIntegerField
0
+from django.dispatch import dispatcher
0
+from django.utils.translation import ugettext as _
0
+
0
+from mptt import models
0
+from mptt.signals import pre_delete, pre_save
0
+from mptt.managers import TreeManager
0
+
0
 VERSION = (0, 2, 'pre')
0
+
0
+__all__ = ('register',)
0
+
0
+class AlreadyRegistered(Exception):
0
+ """
0
+ An attempt was made to register a model for MPTT more than once.
0
+ """
0
+ pass
0
+
0
+registry = []
0
+
0
+def register(model, parent_attr='parent', left_attr='lft', right_attr='rght',
0
+ tree_id_attr='tree_id', level_attr='level',
0
+ tree_manager_attr='tree'):
0
+ """
0
+ Sets the given model class up for Modified Preorder Tree Traversal.
0
+ """
0
+ if model in registry:
0
+ raise AlreadyRegistered(_('The model %s has already been registered.') % model.__name__)
0
+ registry.append(model)
0
+
0
+ # Add tree options to the model's Options
0
+ opts = model._meta
0
+ setattr(opts, 'parent_attr', parent_attr)
0
+ setattr(opts, 'right_attr', right_attr)
0
+ setattr(opts, 'left_attr', left_attr)
0
+ setattr(opts, 'tree_id_attr', tree_id_attr)
0
+ setattr(opts, 'level_attr', level_attr)
0
+ setattr(opts, 'tree_manager_attr', tree_manager_attr)
0
+
0
+ # Add tree fields if they do not exist
0
+ for attr in [left_attr, right_attr, tree_id_attr, level_attr]:
0
+ try:
0
+ opts.get_field(attr)
0
+ except FieldDoesNotExist:
0
+ PositiveIntegerField(
0
+ db_index=True, editable=False).contribute_to_class(model, attr)
0
+
0
+ # Add tree methods for model instances
0
+ setattr(model, 'get_ancestors', models.get_ancestors)
0
+ setattr(model, 'get_children', models.get_children)
0
+ setattr(model, 'get_descendants', models.get_descendants)
0
+ setattr(model, 'get_descendant_count', models.get_descendant_count)
0
+ setattr(model, 'get_next_sibling', models.get_next_sibling)
0
+ setattr(model, 'get_previous_sibling', models.get_previous_sibling)
0
+ setattr(model, 'get_root', models.get_root)
0
+ setattr(model, 'get_siblings', models.get_siblings)
0
+ setattr(model, 'is_child_node', models.is_child_node)
0
+ setattr(model, 'is_leaf_node', models.is_leaf_node)
0
+ setattr(model, 'is_root_node', models.is_root_node)
0
+ setattr(model, 'move_to', models.move_to)
0
+
0
+ # Add a custom tree manager
0
+ TreeManager(parent_attr, left_attr, right_attr, tree_id_attr,
0
+ level_attr).contribute_to_class(model, tree_manager_attr)
0
+ setattr(model, '_tree_manager', getattr(model, tree_manager_attr))
0
+
0
+ # Set up signal receivers to manage the tree when instances of the
0
+ # model are about to be created, have their parent changed or be
0
+ # deleted.
0
+ dispatcher.connect(pre_save, signal=model_signals.pre_save, sender=model)
0
+ dispatcher.connect(pre_delete, signal=model_signals.pre_delete, sender=model)
...
1
2
3
4
5
6
7
 
 
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
...
1
 
 
 
 
 
 
2
3
4
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
5
6
7
0
@@ -1,80 +1,7 @@
0
 """
0
-Functions dealing with Modified Preorder Tree Traversal related setup
0
-and creation of instance methods for a model, given the names of its
0
-tree attributes.
0
-
0
-``treeify`` should be the only function a user of this application need
0
-use directly to set their model up for Modified Preorder Tree Traversal.
0
+New instance methods for Django models which are set up for Modified
0
+Preorder Tree Traversal.
0
 """
0
-from django.db import models
0
-from django.db.models import signals
0
-from django.dispatch import dispatcher
0
-from django.utils.translation import ugettext as _
0
-
0
-from mptt.signals import pre_delete, pre_save
0
-from mptt.managers import TreeManager
0
-
0
-__all__ = ['treeify']
0
-
0
-class AlreadySetUp(Exception):
0
- """
0
- An attempt was made to set up a model for MPTT more than once.
0
- """
0
- pass
0
-
0
-registry = []
0
-
0
-def treeify(model, parent_attr='parent', left_attr='lft', right_attr='rght',
0
- tree_id_attr='tree_id', level_attr='level',
0
- tree_manager_attr='tree'):
0
- """
0
- Sets the given model class up for Modified Preorder Tree Traversal.
0
- """
0
- if model in registry:
0
- raise AlreadySetUp(_('The model %s has already been set up for MPTT.') % model.__name__)
0
- registry.append(model)
0
-
0
- # Add tree options to the model's Options
0
- opts = model._meta
0
- setattr(opts, 'parent_attr', parent_attr)
0
- setattr(opts, 'right_attr', right_attr)
0
- setattr(opts, 'left_attr', left_attr)
0
- setattr(opts, 'tree_id_attr', tree_id_attr)
0
- setattr(opts, 'level_attr', level_attr)
0
- setattr(opts, 'tree_manager_attr', tree_manager_attr)
0
-
0
- # Add tree fields if they do not exist
0
- for attr in [left_attr, right_attr, tree_id_attr, level_attr]:
0
- try:
0
- opts.get_field(attr)
0
- except models.FieldDoesNotExist:
0
- models.PositiveIntegerField(
0
- db_index=True, editable=False).contribute_to_class(model, attr)
0
-
0
- # Add tree methods for model instances
0
- setattr(model, 'get_ancestors', get_ancestors)
0
- setattr(model, 'get_children', get_children)
0
- setattr(model, 'get_descendants', get_descendants)
0
- setattr(model, 'get_descendant_count', get_descendant_count)
0
- setattr(model, 'get_next_sibling', get_next_sibling)
0
- setattr(model, 'get_previous_sibling', get_previous_sibling)
0
- setattr(model, 'get_root', get_root)
0
- setattr(model, 'get_siblings', get_siblings)
0
- setattr(model, 'is_child_node', is_child_node)
0
- setattr(model, 'is_leaf_node', is_leaf_node)
0
- setattr(model, 'is_root_node', is_root_node)
0
- setattr(model, 'move_to', move_to)
0
-
0
- # Add a custom tree manager
0
- TreeManager(parent_attr, left_attr, right_attr, tree_id_attr,
0
- level_attr).contribute_to_class(model, tree_manager_attr)
0
- setattr(model, '_tree_manager', getattr(model, tree_manager_attr))
0
-
0
- # Set up signal receivers to manage the tree when instances of the
0
- # model are about to be created, have their parent changed or be
0
- # deleted.
0
- dispatcher.connect(pre_save, signal=signals.pre_save, sender=model)
0
- dispatcher.connect(pre_delete, signal=signals.pre_delete, sender=model)
0
 
0
 def get_ancestors(self, ascending=False):
0
     """
...
10
11
12
13
14
 
 
15
16
17
 
18
19
20
...
10
11
12
 
 
13
14
15
16
 
17
18
19
20
0
@@ -10,11 +10,11 @@ r"""
0
 ... getattr(n, opts.left_attr), getattr(n, opts.right_attr)) \
0
 ... for n in nodes])
0
 
0
->>> from mptt.models import treeify
0
->>> treeify(Genre)
0
+>>> import mptt
0
+>>> mptt.register(Genre)
0
 Traceback (most recent call last):
0
     ...
0
-AlreadySetUp: The model Genre is already set up for MPTT.
0
+AlreadyRegistered: The model Genre has already been registered.
0
 
0
 # Creation ####################################################################
0
 >>> action = Genre.objects.create(name='Action')
...
1
2
3
 
4
5
6
...
22
23
24
25
26
27
28
29
 
 
 
 
 
...
1
2
 
3
4
5
6
...
22
23
24
 
 
 
 
 
25
26
27
28
29
0
@@ -1,6 +1,6 @@
0
 from django.db import models
0
 
0
-from mptt.models import treeify
0
+import mptt
0
 
0
 class Category(models.Model):
0
     name = models.CharField(max_length=50)
0
@@ -22,8 +22,8 @@ class Node(models.Model):
0
 class Tree(models.Model):
0
     parent = models.ForeignKey('self', null=True, blank=True, related_name='children')
0
 
0
-treeify(Category)
0
-treeify(Genre)
0
-treeify(Node, left_attr='does', right_attr='zis', level_attr='madness',
0
- tree_id_attr='work')
0
-treeify(Tree)
0
+mptt.register(Category)
0
+mptt.register(Genre)
0
+mptt.register(Node, left_attr='does', right_attr='zis', level_attr='madness',
0
+ tree_id_attr='work')
0
+mptt.register(Tree)

Comments

    No one has commented yet.