Merge git://github.com/melinath/philo into melinath
[philo.git] / models.py
index bf11cb5..c17cd70 100644 (file)
--- a/models.py
+++ b/models.py
@@ -5,7 +5,7 @@ from django.contrib.contenttypes import generic
 from django.contrib.contenttypes.models import ContentType
 from django.db import models
 from django.contrib.sites.models import Site
 from django.contrib.contenttypes.models import ContentType
 from django.db import models
 from django.contrib.sites.models import Site
-from utils import fattr
+from philo.utils import fattr
 from django.template import add_to_builtins as register_templatetags
 from django.template import Template as DjangoTemplate
 from django.template import TemplateDoesNotExist
 from django.template import add_to_builtins as register_templatetags
 from django.template import Template as DjangoTemplate
 from django.template import TemplateDoesNotExist
@@ -13,12 +13,13 @@ from django.template import Context, RequestContext
 from django.core.exceptions import ObjectDoesNotExist
 from django.utils import simplejson as json
 from UserDict import DictMixin
 from django.core.exceptions import ObjectDoesNotExist
 from django.utils import simplejson as json
 from UserDict import DictMixin
-from templatetags.containers import ContainerNode
+from philo.templatetags.containers import ContainerNode
 from django.template.loader_tags import ExtendsNode, ConstantIncludeNode, IncludeNode
 from django.template.loader import get_template
 from django.http import Http404, HttpResponse, HttpResponseServerError, HttpResponseRedirect
 from django.core.servers.basehttp import FileWrapper
 from django.conf import settings
 from django.template.loader_tags import ExtendsNode, ConstantIncludeNode, IncludeNode
 from django.template.loader import get_template
 from django.http import Http404, HttpResponse, HttpResponseServerError, HttpResponseRedirect
 from django.core.servers.basehttp import FileWrapper
 from django.conf import settings
+from philo.validators import RedirectValidator
 
 
 def register_value_model(model):
 
 
 def register_value_model(model):
@@ -101,6 +102,13 @@ class Entity(models.Model):
 class Collection(models.Model):
        name = models.CharField(max_length=255)
        description = models.TextField(blank=True, null=True)
 class Collection(models.Model):
        name = models.CharField(max_length=255)
        description = models.TextField(blank=True, null=True)
+       
+       @fattr(short_description='Members')
+       def get_count(self):
+               return self.members.count()
+       
+       def __unicode__(self):
+               return self.name
 
 
 class CollectionMemberManager(models.Manager):
 
 
 class CollectionMemberManager(models.Manager):
@@ -117,6 +125,9 @@ class CollectionMember(models.Model):
        member_content_type = models.ForeignKey(ContentType, verbose_name='Member type')
        member_object_id = models.PositiveIntegerField(verbose_name='Member ID')
        member = generic.GenericForeignKey('member_content_type', 'member_object_id')
        member_content_type = models.ForeignKey(ContentType, verbose_name='Member type')
        member_object_id = models.PositiveIntegerField(verbose_name='Member ID')
        member = generic.GenericForeignKey('member_content_type', 'member_object_id')
+       
+       def __unicode__(self):
+               return u'%s - %s' % (self.collection, self.member)
 
 
 class TreeManager(models.Manager):
 
 
 class TreeManager(models.Manager):
@@ -203,13 +214,16 @@ class InheritableTreeEntity(TreeEntity):
        
        @property
        def instance(self):
        
        @property
        def instance(self):
-               return self.instance_type.get_object_for_this_type(id=self.id)
+               try:
+                       return self.instance_type.get_object_for_this_type(id=self.id)
+               except:
+                       return None
        
        def get_path(self, pathsep='/', field='slug'):
        
        def get_path(self, pathsep='/', field='slug'):
-               path = getattr(self.instance, field, '?')
+               path = getattr(self.instance, field, getattr(self.instance, 'slug', '?'))
                parent = self.parent
                while parent:
                parent = self.parent
                while parent:
-                       path = getattr(parent.instance, field, '?') + pathsep + path
+                       path = getattr(parent.instance, field, getattr(parent.instance, 'slug', '?')) + pathsep + path
                        parent = parent.parent
                return path
        path = property(get_path)
                        parent = parent.parent
                return path
        path = property(get_path)
@@ -235,6 +249,9 @@ class Node(InheritableTreeEntity):
        
        def render_to_response(self, request, path=None, subpath=None):
                return HttpResponseServerError()
        
        def render_to_response(self, request, path=None, subpath=None):
                return HttpResponseServerError()
+               
+       class Meta:
+               unique_together = (('parent', 'slug'),)
 
 
 class MultiNode(Node):
 
 
 class MultiNode(Node):
@@ -259,7 +276,7 @@ class Redirect(Node):
                (302, 'Temporary'),
                (301, 'Permanent'),
        )
                (302, 'Temporary'),
                (301, 'Permanent'),
        )
-       target = models.URLField(help_text='Must be a valid, absolute URL (i.e. http://)')
+       target = models.CharField(max_length=200,validators=[RedirectValidator()])
        status_code = models.IntegerField(choices=STATUS_CODES, default=302, verbose_name='redirect type')
        
        def render_to_response(self, request, path=None, subpath=None):
        status_code = models.IntegerField(choices=STATUS_CODES, default=302, verbose_name='redirect type')
        
        def render_to_response(self, request, path=None, subpath=None):
@@ -353,9 +370,7 @@ class Template(TreeModel):
 
 class Page(Node):
        """
 
 class Page(Node):
        """
-       Represents an HTML page. The page will have a number of related Contentlets
-       depending on the template selected - but these will appear only after the
-       page has been saved with that template.
+       Represents a page - something which is rendered according to a template. The page will have a number of related Contentlets depending on the template selected - but these will appear only after the page has been saved with that template.
        """
        template = models.ForeignKey(Template, related_name='pages')
        title = models.CharField(max_length=255)
        """
        template = models.ForeignKey(Template, related_name='pages')
        title = models.CharField(max_length=255)
@@ -376,14 +391,20 @@ class Contentlet(models.Model):
        name = models.CharField(max_length=255)
        content = models.TextField()
        dynamic = models.BooleanField(default=False)
        name = models.CharField(max_length=255)
        content = models.TextField()
        dynamic = models.BooleanField(default=False)
+       
+       def __unicode__(self):
+               return self.name
 
 
 class ContentReference(models.Model):
        page = models.ForeignKey(Page, related_name='contentreferences')
        name = models.CharField(max_length=255)
        content_type = models.ForeignKey(ContentType, verbose_name='Content type')
 
 
 class ContentReference(models.Model):
        page = models.ForeignKey(Page, related_name='contentreferences')
        name = models.CharField(max_length=255)
        content_type = models.ForeignKey(ContentType, verbose_name='Content type')
-       content_id = models.PositiveIntegerField(verbose_name='Content ID')
+       content_id = models.PositiveIntegerField(verbose_name='Content ID', blank=True, null=True)
        content = generic.GenericForeignKey('content_type', 'content_id')
        content = generic.GenericForeignKey('content_type', 'content_id')
+       
+       def __unicode__(self):
+               return self.name
 
 
 register_templatetags('philo.templatetags.containers')
 
 
 register_templatetags('philo.templatetags.containers')