From: Stephen Burrows Date: Tue, 5 Oct 2010 21:49:59 +0000 (-0400) Subject: Merge branch 'embed' X-Git-Tag: philo-0.9~30^2 X-Git-Url: http://git.ithinksw.org/philo.git/commitdiff_plain/b768cb7ae3b355a09bbf554522584db729d23c14?hp=89ccd16497c79398a27387bf42016e888afec9eb Merge branch 'embed' --- diff --git a/contrib/penfield/models.py b/contrib/penfield/models.py index f927a58..c9c024c 100644 --- a/contrib/penfield/models.py +++ b/contrib/penfield/models.py @@ -1,6 +1,6 @@ from django.db import models from django.conf import settings -from philo.models import Tag, Titled, Entity, MultiView, Page, register_value_model +from philo.models import Tag, Titled, Entity, MultiView, Page, register_value_model, TemplateField from philo.exceptions import ViewCanNotProvideSubpath from django.conf.urls.defaults import url, patterns, include from django.core.urlresolvers import reverse @@ -257,8 +257,8 @@ class NewsletterArticle(Entity, Titled): newsletter = models.ForeignKey(Newsletter, related_name='articles') authors = models.ManyToManyField(getattr(settings, 'PHILO_PERSON_MODULE', 'auth.User'), related_name='newsletterarticles') date = models.DateTimeField(default=datetime.now) - lede = models.TextField(null=True, blank=True) - full_text = models.TextField() + lede = TemplateField(null=True, blank=True, verbose_name='Summary') + full_text = TemplateField() tags = models.ManyToManyField(Tag, related_name='newsletterarticles', blank=True, null=True) class Meta: diff --git a/models/__init__.py b/models/__init__.py index 5d39ac6..76d7812 100644 --- a/models/__init__.py +++ b/models/__init__.py @@ -9,4 +9,5 @@ from django.contrib.sites.models import Site register_value_model(User) register_value_model(Group) -register_value_model(Site) \ No newline at end of file +register_value_model(Site) +register_templatetags('philo.templatetags.embed') \ No newline at end of file diff --git a/templatetags/embed.py b/templatetags/embed.py new file mode 100644 index 0000000..8fb240d --- /dev/null +++ b/templatetags/embed.py @@ -0,0 +1,176 @@ +from django import template +from django.contrib.contenttypes.models import ContentType +from django.conf import settings +from philo.utils import LOADED_TEMPLATE_ATTR + + +register = template.Library() + + +class ConstantEmbedNode(template.Node): + """Analogous to the ConstantIncludeNode, this node precompiles several variables necessary for correct rendering - namely the referenced instance or the included template.""" + def __init__(self, content_type, varname, object_pk=None, template_name=None, kwargs=None): + assert template_name is not None or object_pk is not None + self.content_type = content_type + self.varname = varname + + kwargs = kwargs or {} + for k, v in kwargs.items(): + kwargs[k] = template.Variable(v) + self.kwargs = kwargs + + if object_pk is not None: + self.compile_instance(object_pk) + else: + self.instance = None + + if template_name is not None: + self.compile_template(template_name[1:-1]) + else: + self.template = None + + def compile_instance(self, object_pk): + self.object_pk = object_pk + model = self.content_type.model_class() + try: + self.instance = model.objects.get(pk=object_pk) + except model.DoesNotExist: + if not hasattr(self, 'object_pk') and settings.TEMPLATE_DEBUG: + # Then it's a constant node. + raise + self.instance = False + + def compile_template(self, template_name): + try: + self.template = template.loader.get_template(template_name) + except template.TemplateDoesNotExist: + if not hasattr(self, 'template_name') and settings.TEMPLATE_DEBUG: + # Then it's a constant node. + raise + self.template = False + + def render(self, context): + if self.template is not None: + if self.template is False: + return settings.TEMPLATE_STRING_IF_INVALID + + if self.varname not in context: + context[self.varname] = {} + context[self.varname][self.content_type] = self.template + + return '' + + # Otherwise self.instance should be set. Render the instance with the appropriate template! + if self.instance is None or self.instance is False: + return settings.TEMPLATE_STRING_IF_INVALID + + return self.render_template(context, self.instance) + + def render_template(self, context, instance): + try: + t = context[self.varname][self.content_type] + except KeyError: + return settings.TEMPLATE_STRING_IF_INVALID + + context.push() + context['embedded'] = instance + kwargs = {} + for k, v in self.kwargs.items(): + kwargs[k] = v.resolve(context) + context.update(kwargs) + t_rendered = t.render(context) + context.pop() + return t_rendered + + +class EmbedNode(ConstantEmbedNode): + def __init__(self, content_type, varname, object_pk=None, template_name=None, kwargs=None): + assert template_name is not None or object_pk is not None + self.content_type = content_type + self.varname = varname + + kwargs = kwargs or {} + for k, v in kwargs.items(): + kwargs[k] = template.Variable(v) + self.kwargs = kwargs + + if object_pk is not None: + self.object_pk = template.Variable(object_pk) + else: + self.object_pk = None + self.instance = None + + if template_name is not None: + self.template_name = template.Variable(template_name) + else: + self.template_name = None + self.template = None + + def render(self, context): + if self.template_name is not None: + template_name = self.template_name.resolve(context) + self.compile_template(template_name) + + if self.object_pk is not None: + object_pk = self.object_pk.resolve(context) + self.compile_instance(object_pk) + + return super(EmbedNode, self).render(context) + + +def get_embedded(self): + return self.template + + +setattr(ConstantEmbedNode, LOADED_TEMPLATE_ATTR, property(get_embedded)) + + +def do_embed(parser, token): + """ + The {% embed %} tag can be used in three ways: + {% embed as %} :: This sets which variable will be used to track embedding template names for the current context. Default: "embed" + {% embed . with