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
-~----------~----~----~----~------~----~------~--~---

Reply via email to