This code will generate a model that has a nice interface for people constructing sites organized around hierarchical menus. When adding a page, the current structure of the site shows up like this:
root node -child node --child of a child node If a loop is detected during insertion, the page is moved to the root of the hierarchy. The code is probably terribly inefficient. I couldn't get the preorder traversal tree working to save my life, so I devised this. Let me know what you think. Dan from django.db import models, connection from django.db.models.query import Q import pprint weight_options = [] for item in range(-10,11): weight_options.append([item, item]) class Page(models.Model): parent = models.ForeignKey('self', null=True, blank=True) title = models.CharField(maxlength=100, core=True) slug = models.SlugField(help_text='Friendly URL', unique=True, prepopulate_from=('title',)) alias = models.CharField(blank=True, maxlength=100) weight = models.IntegerField(help_text='Lower weights show up earlier in lists. If items have the same weight, they are sorted by name.', default=0, choices=weight_options) body = models.TextField(blank=True, null=True) created = models.DateTimeField('Date Created', auto_now_add=True) modified = models.DateTimeField('Date Last Modified', auto_now=True) index = models.IntegerField(default=0, help_text='This field is used internally to properly arrange the menu. Please do not edit this field.') depth = models.IntegerField(default=0, help_text='This field is used to format the menu. Please do not edit this field.') class Admin: fields = ( ('Page', { 'fields' : ('title', 'body',) }), ('Menu', { 'fields' : ('parent', 'weight',) }), ('Advanced', { 'fields': ('slug', 'alias', 'index', 'depth',) , 'classes': 'collapse' }), ) list_display=('__str__', 'admin_links', 'created', 'modified',) list_filter=('modified', 'created',) search_fields=('title', 'body',) ordering=('index',) class Meta: ordering = ('index',) def get_absolute_url(self): if self.alias: return self.alias else: return '/pages/%s' % self.slug def admin_links(self): return '<a href="%s">edit</a> | <a href="%s">view</a> | <a href="%s/delete">delete</a>' % (self.id, self.get_absolute_url(), self.id) admin_links.allow_tags = True admin_links.short_description = 'Actions' def __str__(self): return '-' * self.depth + self.title def ancestors(self): list = [] page = self while page: if page in list: raise 'loop detected' list.append(page) page = page.parent return list def save(self): super(Page, self).save() # Make sure there are no loops in the hierarchy try: self.ancestors() except: self.parent = None # Call the super's save, so that the DB is correct before we modify it. super(Page, self).save() def get_order_recurse(parent, depth, index): pages = Page.objects.filter(parent=parent).order_by('weight') for page in pages: page.index = index page.depth = depth super(Page, page).save() index = get_order_recurse(page, depth + 1, index + 1) return index index = 0 pages = Page.objects.filter(parent__isnull=True).order_by('weight') for page in pages: page.index = index page.depth = 0 super(Page, page).save() index = get_order_recurse(page, 1, index + 1) --~--~---------~--~----~------------~-------~--~----~ You received this message because you are subscribed to the Google Groups "Django users" group. To post to this group, send email to django-users@googlegroups.com To unsubscribe from this group, send email to [EMAIL PROTECTED] For more options, visit this group at http://groups.google.com/group/django-users -~----------~----~----~----~------~----~------~--~---