Merge branch 'master' of http://git.ithinksw.org/philo
[philo.git] / admin.py
index f63b576..ce79635 100644 (file)
--- a/admin.py
+++ b/admin.py
@@ -7,8 +7,12 @@ from django.utils.translation import ugettext as _
 from django.utils.safestring import mark_safe
 from django.utils.html import escape
 from django.utils.text import truncate_words
-from models import *
+from philo.models import *
 from django.core.exceptions import ValidationError, ObjectDoesNotExist
+from validators import TreeParentValidator, TreePositionValidator
+
+
+COLLAPSE_CLASSES = ('collapse', 'collapse-closed', 'closed',)
 
 
 class AttributeInline(generic.GenericTabularInline):
@@ -16,7 +20,7 @@ class AttributeInline(generic.GenericTabularInline):
        ct_fk_field = 'entity_object_id'
        model = Attribute
        extra = 1
-       classes = ('collapse-closed',)
+       template = 'admin/philo/edit_inline/tabular_collapse.html'
        allow_add = True
 
 
@@ -25,7 +29,7 @@ class RelationshipInline(generic.GenericTabularInline):
        ct_fk_field = 'entity_object_id'
        model = Relationship
        extra = 1
-       classes = ('collapse-closed',)
+       template = 'admin/philo/edit_inline/tabular_collapse.html'
        allow_add = True
 
 
@@ -38,35 +42,18 @@ class CollectionMemberInline(admin.TabularInline):
        fk_name = 'collection'
        model = CollectionMember
        extra = 1
-       classes = ('collapse-closed',)
+       classes = COLLAPSE_CLASSES
        allow_add = True
+       fields = ('member_content_type', 'member_object_id', 'index',)
 
 
 class CollectionAdmin(admin.ModelAdmin):
        inlines = [CollectionMemberInline]
+       list_display = ('name', 'description', 'get_count')
 
 
-class TemplateAdmin(admin.ModelAdmin):
-       prepopulated_fields = {'slug': ('name',)}
-       fieldsets = (
-               (None, {
-                       'fields': ('parent', 'name', 'slug')
-               }),
-               ('Documentation', {
-                       'classes': ('collapse', 'collapse-closed'),
-                       'fields': ('documentation',)
-               }),
-               (None, {
-                       'fields': ('code',)
-               }),
-               ('Advanced', {
-                       'classes': ('collapse','collapse-closed'),
-                       'fields': ('mimetype',)
-               }),
-       )
-       save_on_top = True
-       save_as = True
-       list_display = ('__unicode__', 'slug', 'get_path',)
+class NodeAdmin(EntityAdmin):
+       pass
 
 
 class ModelLookupWidget(forms.TextInput):
@@ -95,50 +82,105 @@ class ModelLookupWidget(forms.TextInput):
                                pass
                return mark_safe(output)
 
-class NodeForm(forms.ModelForm):
-       
+
+class TreeForm(forms.ModelForm):
        def __init__(self, *args, **kwargs):
-               super(NodeForm, self).__init__(*args, **kwargs)
+               super(TreeForm, self).__init__(*args, **kwargs)
                instance = self.instance
-               try:
-                       self.fields['parent'].queryset = instance.node_ptr.__class__.objects.exclude(id=instance.id)
-               except ObjectDoesNotExist:
-                       pass
+               instance_class = self.get_instance_class()
+               
+               if instance_class is not None:
+                       try:
+                               self.fields['parent'].queryset = instance_class.objects.exclude(id=instance.id)
+                       except ObjectDoesNotExist:
+                               pass
+                       
+               self.fields['parent'].validators = [TreeParentValidator(*self.get_validator_args())]
+       
+       def get_instance_class(self):
+               return self.instance.__class__
+               
+       def get_validator_args(self):
+               return [self.instance]
        
        def clean(self):
                cleaned_data = self.cleaned_data
-               parent = self.cleaned_data['parent']
-               self.instance.validate_parents(parent)
-                       
+               
                try:
-                       Node.objects.get(slug=self.cleaned_data['slug'], parent=parent)
-                       raise ValidationError("A node with that path (parent and slug) already exists.")
-               except ObjectDoesNotExist:
+                       parent = cleaned_data['parent']
+                       slug = cleaned_data['slug']
+                       obj_class = self.get_instance_class()
+                       tpv = TreePositionValidator(parent, slug, obj_class)
+                       tpv(self.instance)
+               except KeyError:
                        pass
                
                return cleaned_data
 
+
+class NodeForm(TreeForm):
+       def get_instance_class(self):
+               return Node
+               
+       def get_validator_args(self):
+               return [self.instance, 'instance']
+
+
 class PageAdminForm(NodeForm):
        class Meta:
-               model=Page
+               model = Page
+
 
 class RedirectAdminForm(NodeForm):
        class Meta:
-               model=Redirect
-               
+               model = Redirect
+
+
 class FileAdminForm(NodeForm):
        class Meta:
-               model=File
+               model = File
+
 
-class PageAdmin(EntityAdmin):
+class RedirectAdmin(NodeAdmin):
+       fieldsets = (
+               (None, {
+                       'fields': ('slug', 'target', 'status_code')
+               }),
+               ('URL/Tree/Hierarchy', {
+                       'classes': COLLAPSE_CLASSES,
+                       'fields': ('parent',)
+               }),
+       )
+       list_display=('slug', 'target', 'path', 'status_code',)
+       list_filter=('status_code',)
+       form = RedirectAdminForm
+
+
+class FileAdmin(NodeAdmin):
+       prepopulated_fields = {'slug': ('file',)}
+       fieldsets = (
+               (None, {
+                       'fields': ('file', 'slug', 'mimetype')
+               }),
+               ('URL/Tree/Hierarchy', {
+                       'classes': COLLAPSE_CLASSES,
+                       'fields': ('parent',)
+               }),
+       )
+       form=FileAdminForm
+       list_display=('slug', 'mimetype', 'path', 'file',)
+
+
+class PageAdmin(NodeAdmin):
+       add_form_template = 'admin/philo/page/add_form.html'
        prepopulated_fields = {'slug': ('title',)}
        fieldsets = (
                (None, {
-                       'fields': ('title', 'template')
+                       'fields': ('title', 'slug', 'template')
                }),
                ('URL/Tree/Hierarchy', {
-                       'classes': ('collapse', 'collapse-closed'),
-                       'fields': ('parent', 'slug')
+                       'classes': COLLAPSE_CLASSES,
+                       'fields': ('parent',)
                }),
        )
        list_display = ('title', 'path', 'template')
@@ -149,8 +191,11 @@ class PageAdmin(EntityAdmin):
        def get_fieldsets(self, request, obj=None, **kwargs):
                fieldsets = list(self.fieldsets)
                if obj: # if no obj, creating a new page, thus no template set, thus no containers
-                       page = obj
-                       template = page.template
+                       template = obj.template
+                       if template.documentation:
+                               fieldsets.append(('Template Documentation', {
+                                       'description': template.documentation
+                               }))
                        contentlet_containers, contentreference_containers = template.containers
                        for container_name in contentlet_containers:
                                fieldsets.append((('Container: %s' % container_name), {
@@ -183,7 +228,7 @@ class PageAdmin(EntityAdmin):
                                initial_content = None
                                try:
                                        initial_content = page.contentreferences.get(name__exact=container_name, content_type=container_content_type).content.pk
-                               except ContentReference.DoesNotExist:
+                               except (ContentReference.DoesNotExist, AttributeError):
                                        pass
                                form.base_fields[('contentreference_container_%s' % container_name)] = forms.ModelChoiceField(label='References', widget=ModelLookupWidget(container_content_type), initial=initial_content, required=False, queryset=container_content_type.model_class().objects.all())
                return form
@@ -204,19 +249,42 @@ class PageAdmin(EntityAdmin):
                for container_name, container_content_type in contentreference_containers:
                        if ('contentreference_container_%s' % container_name) in form.cleaned_data:
                                content = form.cleaned_data[('contentreference_container_%s' % container_name)]
-                               contentreference, created = page.contentreferences.get_or_create(name=container_name, defaults={'content': content})
-                               if not created:
-                                       contentreference.content = content
-                                       contentreference.save()
+                               try:
+                                       contentreference = page.contentreferences.get(name=container_name)
+                               except:
+                                       contentreference = ContentReference(name=container_name, page=page, content_type=container_content_type)
+                                       
+                               if content == None:
+                                       contentreference.content_id = None
+                               else:
+                                       contentreference.content_id = content.id
+                               
+                               contentreference.save()
 
-class RedirectAdmin(admin.ModelAdmin):
-       list_display=('slug', 'target', 'path', 'status_code',)
-       list_filter=('status_code',)
-       form = RedirectAdminForm
 
-class FileAdmin(admin.ModelAdmin):
-       form=FileAdminForm
-       list_display=('slug', 'mimetype', 'path', 'file',)
+class TemplateAdmin(admin.ModelAdmin):
+       prepopulated_fields = {'slug': ('name',)}
+       fieldsets = (
+               (None, {
+                       'fields': ('parent', 'name', 'slug')
+               }),
+               ('Documentation', {
+                       'classes': COLLAPSE_CLASSES,
+                       'fields': ('documentation',)
+               }),
+               (None, {
+                       'fields': ('code',)
+               }),
+               ('Advanced', {
+                       'classes': COLLAPSE_CLASSES,
+                       'fields': ('mimetype',)
+               }),
+       )
+       save_on_top = True
+       save_as = True
+       list_display = ('__unicode__', 'slug', 'get_path',)
+       form = TreeForm
+
 
 admin.site.register(Collection, CollectionAdmin)
 admin.site.register(Redirect, RedirectAdmin)