Merge branch 'master' of git://github.com/melinath/philo
authorJoseph Spiros <joseph.spiros@ithinksw.com>
Fri, 20 Aug 2010 21:21:27 +0000 (17:21 -0400)
committerJoseph Spiros <joseph.spiros@ithinksw.com>
Fri, 20 Aug 2010 21:21:27 +0000 (17:21 -0400)
* 'master' of git://github.com/melinath/philo:
  Re-tweaked page add form to preserve 'continue on normal save' functionality. This is implemented with javascript and will probably break some time in the future, but there doesn't seem to be a better way to do it at the moment. Fixes bug #8.
  Tweaked page add_form template. Fixes bug #8.
  Moved templateform to forms.py in preparation for experimentation with page forms.
  Added collapse classes to attribute and relationship inlines on entities.
  Added template code validation to the admin. This essentially addresses bug #14 by catching errors with validation on templates instead of letting it show up as a server error later. (Note that there should still be better validation on Pages, as deletion of a template say on the filesystem could render a db-driven template invalid.)
  Set TreeModel slug field length to 255 to match Titled

admin/base.py
admin/pages.py
forms.py
models/base.py
templates/admin/philo/page/add_form.html

index 457db17..f8485d2 100644 (file)
@@ -13,6 +13,7 @@ class AttributeInline(generic.GenericTabularInline):
        extra = 1
        template = 'admin/philo/edit_inline/tabular_collapse.html'
        allow_add = True
+       classes = COLLAPSE_CLASSES
 
 
 class RelationshipInline(generic.GenericTabularInline):
@@ -22,6 +23,7 @@ class RelationshipInline(generic.GenericTabularInline):
        extra = 1
        template = 'admin/philo/edit_inline/tabular_collapse.html'
        allow_add = True
+       classes = COLLAPSE_CLASSES
 
 
 class EntityAdmin(admin.ModelAdmin):
index ab89011..52238da 100644 (file)
@@ -1,9 +1,11 @@
 from django.contrib import admin
 from django import forms
+from django.template import Template as DjangoTemplate
 from philo.admin import widgets
 from philo.admin.base import COLLAPSE_CLASSES
 from philo.admin.nodes import ViewAdmin
 from philo.models.pages import Page, Template, Contentlet, ContentReference
+from philo.forms import TemplateForm
 
 
 class PageAdmin(ViewAdmin):
@@ -113,6 +115,7 @@ class TemplateAdmin(admin.ModelAdmin):
        save_on_top = True
        save_as = True
        list_display = ('__unicode__', 'slug', 'get_path',)
+       form = TemplateForm
 
 
 admin.site.register(Page, PageAdmin)
index 907e54d..8050d39 100644 (file)
--- a/forms.py
+++ b/forms.py
@@ -1,6 +1,8 @@
+from django.core.exceptions import ValidationError
 from django.forms.models import model_to_dict, fields_for_model, ModelFormMetaclass, ModelForm
+from django.template import loader, loader_tags, TemplateDoesNotExist, Context, Template as DjangoTemplate
 from django.utils.datastructures import SortedDict
-from philo.models import Entity
+from philo.models import Entity, Template
 from philo.models.fields import RelationshipField
 from philo.utils import fattr
 
@@ -86,4 +88,35 @@ class EntityForm(EntityFormBase): # Would inherit from ModelForm directly if it
                        instance.save()
                        self.save_m2m()
                
-               return instance
\ No newline at end of file
+               return instance
+
+
+def validate_template(template):
+       """
+       Makes sure that the template and all included or extended templates are valid.
+       """     
+       for node in template.nodelist:
+               try:
+                       if isinstance(node, loader_tags.ExtendsNode):
+                               extended_template = node.get_parent(Context())
+                               validate_template(extended_template)
+                       elif isinstance(node, loader_tags.IncludeNode):
+                               included_template = loader.get_template(node.template_name.resolve(Context()))
+                               validate_template(extended_template)
+               except Exception, e:
+                       raise ValidationError("Template code invalid. Error was: %s: %s" % (e.__class__.__name__, e))
+
+
+class TemplateForm(ModelForm):
+       def clean_code(self):
+               code = self.cleaned_data['code']
+               try:
+                       t = DjangoTemplate(code)
+               except Exception, e:
+                       raise ValidationError("Template code invalid. Error was: %s: %s" % (e.__class__.__name__, e))
+
+               validate_template(t)
+               return code
+
+       class Meta:
+               model = Template
\ No newline at end of file
index 9da9230..27c45dc 100644 (file)
@@ -241,7 +241,7 @@ class TreeManager(models.Manager):
 class TreeModel(models.Model):
        objects = TreeManager()
        parent = models.ForeignKey('self', related_name='children', null=True, blank=True)
-       slug = models.SlugField()
+       slug = models.SlugField(max_length=255)
        
        def has_ancestor(self, ancestor):
                parent = self
index 8937463..67f6ec4 100644 (file)
@@ -1,6 +1,22 @@
 {% extends "admin/change_form.html" %}
 {% load i18n %}
 
+{% block extrahead %}{{ block.super }}
+<!-- This will break if anything ever changes and may not work in all browsers. Sad face. -->
+<script type='text/javascript'>
+(function($){
+       $(function(){
+               $('#page_form input[type=submit]').click(function(e){
+                       if (e.target.name == '_addanother') {
+                               hidden = document.getElementById('page_form')._continue[0]
+                               hidden.parentNode.removeChild(hidden)
+                       }
+               })
+       })
+}(django.jQuery));
+</script>
+{% endblock %}
+
 {% block form_top %}
        <p>{% trans "First, choose a template. After saving, you'll be able to provide additional content for containers." %}</p>
        <input type="hidden" name="_continue" value="1" />