Ticket #202: product-models-mptt-r3.diff
| File product-models-mptt-r3.diff, 6.0 kB (added by hkpark, 1 year ago) |
|---|
-
models.py
old new 11 11 from decimal import Decimal 12 12 from django.conf import settings 13 13 from django.core import validators, urlresolvers 14 from django.db import models 14 from django.db import models, connection, transaction 15 15 from django.utils.translation import ugettext_lazy as _ 16 16 from satchmo.configuration import config_value 17 17 from satchmo.shop.utils import url_join … … 38 38 name = models.CharField(_("Name"), core=True, max_length=200) 39 39 slug = models.SlugField(prepopulate_from=('name',), 40 40 help_text=_("Used for URLs")) 41 parent = models.ForeignKey('self', blank=True, null=True, 42 related_name='child') 41 parent = models.ForeignKey('self', blank=True, null=True, related_name='child') 43 42 meta = models.TextField(_("Meta Description"), blank=True, null=True, 44 43 help_text=_("Meta description for this category")) 45 44 description = models.TextField(_("Description"), blank=True, 46 45 help_text="Optional") 47 46 47 # category of which tree since we can have multiple root categories 48 tree_id = models.PositiveIntegerField(db_index=True) 49 50 #Left and Right are keywords in SQL so we purposely misspell them 51 lft = models.PositiveIntegerField(db_index=True) 52 rght = models.PositiveIntegerField(db_index=True) 53 48 54 def _recurse_for_parents(self, cat_obj): 49 55 p_list = [] 50 if cat_obj.parent_id: 51 p = cat_obj.parent 52 p_list.append(p) 53 if p != self: 54 more = self._recurse_for_parents(p) 55 p_list.extend(more) 56 if cat_obj == self and p_list: 57 p_list.reverse() 56 if cat_obj.parent: 57 try: 58 #removes the recursion and gets the parents in one query 59 p_list = Category.objects.filter(lft__lt=cat_obj.lft, rght__gt=cat_obj.rght, tree_id=cat_obj.tree_id).order_by('lft') 60 except IndexError: 61 pass 58 62 return p_list 59 63 64 #def _set_parent(self, parent): 65 # # if parent is set, get or create the parent node 66 # self.parent, created = Category.objects.get_or_create( 67 # name=parent.name, slug=parent.slug, description=parent.description, 68 # defaults={'tree_id': self.next_tree_id, 'lft': 1, 'rght': 2}) 69 # 70 #def _get_parent(self): 71 # return self.parent_category 72 # 73 #parent = property(_get_parent, _set_parent) 74 60 75 def get_absolute_url(self): 61 76 parents = self._recurse_for_parents(self) 62 77 slug_list = [cat.slug for cat in parents] … … 87 102 name_list.append(self.name) 88 103 return self.get_separator().join(name_list) 89 104 105 def _get_next_tree_id(self): 106 sql = 'select max(tree_id) from %s' % self._meta.db_table 107 cursor = connection.cursor() 108 cursor.execute(sql) 109 row = cursor.fetchone() 110 return row[0] and (row[0] + 1) or 1 111 112 #multi-root categories, need a unique tree id for the categories 113 next_tree_id = property(_get_next_tree_id) 114 115 @transaction.commit_on_success 90 116 def save(self): 91 parents = self._recurse_for_parents(self) 92 if self in parents: 93 raise validators.ValidationError(_("You must not save a category in itself!")) 117 #parents = self._recurse_for_parents(self) 118 #if self in parents: 119 # raise validators.ValidationError(_("You must not save a category in itself!")) 120 # If parent category is set, we need to update the whole tree to the right of it. 121 if self.parent: 122 123 cursor = connection.cursor() 124 125 #Left and Right are keywords in SQL so we purposely misspell them 126 #and keep misspellings in variable names intently 127 target_rght = self.parent.rght - 1 128 129 cursor.execute("UPDATE `%s` " \ 130 "SET `rght` = `rght` + 2 " \ 131 "WHERE tree_id = '%i' " 132 "AND `rght` > %i" % (self._meta.db_table, self.parent.tree_id, int(target_rght))) 133 134 cursor.execute("UPDATE `%s` " \ 135 "SET `lft` = `lft` + 2 " \ 136 "WHERE tree_id = '%i' " 137 "AND `lft` > %i" % (self._meta.db_table, self.parent.tree_id, int(target_rght))) 138 139 self.tree_id = self.parent.tree_id 140 self.lft = target_rght + 1 141 self.rght = target_rght + 2 142 else: 143 # can't find a parent so set it as a root category 144 self.tree_id = self.next_tree_id 145 self.lft = 1 146 self.rght = 2 147 94 148 super(Category, self).save() 95 149 96 150 def _flatten(self, L): … … 103 157 104 158 def _recurse_for_children(self, node): 105 159 children = [] 106 children.append(node) 107 for child in node.child.all(): 108 if child != self: 109 children_list = self._recurse_for_children(child) 110 children.append(children_list) 160 if node: 161 try: 162 #removes the recursion and gets the children in one query 163 children = Category.objects.filter(lft__gt=node.lft, rght__lt=node.rght, tree_id=node.tree_id).order_by('lft') 164 except IndexError: 165 pass 111 166 return children 112 167 113 168 def get_all_children(self): … … 115 170 Gets a list of all of the children categories. 116 171 """ 117 172 children_list = self._recurse_for_children(self) 118 flat_list = self._flatten(children_list[1:]) 119 return flat_list 173 return self._flatten(children_list[0:1]) 120 174 121 175 class Admin: 122 176 list_display = ('name', '_parents_repr') 123 ordering = [' parent', 'name']177 ordering = ['tree_id', 'lft', 'name'] 124 178 125 179 class Meta: 126 ordering = [' parent', 'name']180 ordering = ['tree_id', 'lft', 'name'] 127 181 verbose_name = _("Category") 128 182 verbose_name_plural = _("Categories") 129 183
