From 46e38bc758413be6d266a01b7e12f906a31abc34 Mon Sep 17 00:00:00 2001 From: James Tauber Date: Sun, 5 Feb 2012 15:03:30 -0500 Subject: [PATCH 1/6] initial sponsorship app adapted from DjangoCon --- .../apps/sponsorship/__init__.py | 0 symposion_project/apps/sponsorship/admin.py | 7 +++ symposion_project/apps/sponsorship/models.py | 32 ++++++++++++++ .../apps/sponsorship/templatetags/__init__.py | 0 .../templatetags/sponsorship_tags.py | 43 +++++++++++++++++++ 5 files changed, 82 insertions(+) create mode 100644 symposion_project/apps/sponsorship/__init__.py create mode 100644 symposion_project/apps/sponsorship/admin.py create mode 100644 symposion_project/apps/sponsorship/models.py create mode 100644 symposion_project/apps/sponsorship/templatetags/__init__.py create mode 100644 symposion_project/apps/sponsorship/templatetags/sponsorship_tags.py diff --git a/symposion_project/apps/sponsorship/__init__.py b/symposion_project/apps/sponsorship/__init__.py new file mode 100644 index 00000000..e69de29b diff --git a/symposion_project/apps/sponsorship/admin.py b/symposion_project/apps/sponsorship/admin.py new file mode 100644 index 00000000..6df73af2 --- /dev/null +++ b/symposion_project/apps/sponsorship/admin.py @@ -0,0 +1,7 @@ +from django.contrib import admin + +from symposion.sponsors.models import SponsorLevel, Sponsor + + +admin.site.register(SponsorLevel) +admin.site.register(Sponsor) diff --git a/symposion_project/apps/sponsorship/models.py b/symposion_project/apps/sponsorship/models.py new file mode 100644 index 00000000..743f6d75 --- /dev/null +++ b/symposion_project/apps/sponsorship/models.py @@ -0,0 +1,32 @@ +import datetime + +from django.db import models + + +class SponsorLevel(models.Model): + + name = models.CharField(max_length=100) + order = models.IntegerField(default=0) + description = models.TextField(blank=True) + + class Meta: + ordering = ["order"] + + def __unicode__(self): + return self.name + + +class Sponsor(models.Model): + + name = models.CharField(max_length=100) + external_url = models.URLField("external URL") + annotation = models.TextField(blank=True) + contact_name = models.CharField(max_length=100) + contact_email = models.EmailField(u"Contact e\u2011mail") + logo = models.ImageField(upload_to="sponsor_logos/") + level = models.ForeignKey(SponsorLevel) + added = models.DateTimeField(default=datetime.datetime.now) + active = models.BooleanField(default=False) + + def __unicode__(self): + return self.name diff --git a/symposion_project/apps/sponsorship/templatetags/__init__.py b/symposion_project/apps/sponsorship/templatetags/__init__.py new file mode 100644 index 00000000..e69de29b diff --git a/symposion_project/apps/sponsorship/templatetags/sponsorship_tags.py b/symposion_project/apps/sponsorship/templatetags/sponsorship_tags.py new file mode 100644 index 00000000..baae404b --- /dev/null +++ b/symposion_project/apps/sponsorship/templatetags/sponsorship_tags.py @@ -0,0 +1,43 @@ +from django import template + +from sponsorship.models import Sponsor + + +register = template.Library() + + +class SponsorsNode(template.Node): + + @classmethod + def handle_token(cls, parser, token): + bits = token.split_contents() + if len(bits) != 4: + raise template.TemplateSyntaxError("%r takes exactly three arguments " + "(second argument must be 'as')" % bits[0]) + if bits[2] != "as": + raise template.TemplateSyntaxError("Second argument to %r must be " + "'as'" % bits[0]) + return cls(bits[1], bits[3]) + + def __init__(self, level, context_var): + self.level = template.Variable(level) + self.context_var = context_var + + def render(self, context): + level = self.level.resolve(context) + queryset = Sponsor.objects.filter( + level__name__iexact = level, + active = True + ).order_by( + "added" + ) + context[self.context_var] = queryset + return u"" + + +@register.tag +def sponsors(parser, token): + """ + {% sponsors "gold" as sponsors %} + """ + return SponsorsNode.handle_token(parser, token) From 64569bccc72a7c30c163eac23dcd45c7ad8ff6b5 Mon Sep 17 00:00:00 2001 From: James Tauber Date: Sun, 5 Feb 2012 15:51:27 -0500 Subject: [PATCH 2/6] fixed incorrect module name in import --- symposion_project/apps/sponsorship/admin.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/symposion_project/apps/sponsorship/admin.py b/symposion_project/apps/sponsorship/admin.py index 6df73af2..b69aff91 100644 --- a/symposion_project/apps/sponsorship/admin.py +++ b/symposion_project/apps/sponsorship/admin.py @@ -1,6 +1,6 @@ from django.contrib import admin -from symposion.sponsors.models import SponsorLevel, Sponsor +from sponsorship.models import SponsorLevel, Sponsor admin.site.register(SponsorLevel) From e4e7b890a2a6f39054cc414711de34a51d64850a Mon Sep 17 00:00:00 2001 From: James Tauber Date: Sun, 5 Feb 2012 17:13:06 -0500 Subject: [PATCH 3/6] added sponsorship template tags and template fragments; improved admin --- symposion_project/apps/sponsorship/admin.py | 4 +- symposion_project/apps/sponsorship/models.py | 3 + .../templatetags/sponsorship_tags.py | 65 ++++++++++++++----- symposion_project/requirements/project.txt | 5 +- symposion_project/settings.py | 2 + .../sponsorship/_horizontal_by_level.html | 11 ++++ .../templates/sponsorship/_sponsor_link.html | 10 +++ .../sponsorship/_vertical_by_level.html | 13 ++++ .../templates/sponsorship/_wall.html | 7 ++ 9 files changed, 99 insertions(+), 21 deletions(-) create mode 100644 symposion_project/templates/sponsorship/_horizontal_by_level.html create mode 100644 symposion_project/templates/sponsorship/_sponsor_link.html create mode 100644 symposion_project/templates/sponsorship/_vertical_by_level.html create mode 100644 symposion_project/templates/sponsorship/_wall.html diff --git a/symposion_project/apps/sponsorship/admin.py b/symposion_project/apps/sponsorship/admin.py index b69aff91..e234e794 100644 --- a/symposion_project/apps/sponsorship/admin.py +++ b/symposion_project/apps/sponsorship/admin.py @@ -3,5 +3,5 @@ from django.contrib import admin from sponsorship.models import SponsorLevel, Sponsor -admin.site.register(SponsorLevel) -admin.site.register(Sponsor) +admin.site.register(SponsorLevel, list_display=("order", "name")) +admin.site.register(Sponsor, list_display=("name", "level", "added", "active"), list_filter = ("level", )) diff --git a/symposion_project/apps/sponsorship/models.py b/symposion_project/apps/sponsorship/models.py index 743f6d75..f77de766 100644 --- a/symposion_project/apps/sponsorship/models.py +++ b/symposion_project/apps/sponsorship/models.py @@ -14,6 +14,9 @@ class SponsorLevel(models.Model): def __unicode__(self): return self.name + + def sponsors(self): + return self.sponsor_set.filter(active=True).order_by("added") class Sponsor(models.Model): diff --git a/symposion_project/apps/sponsorship/templatetags/sponsorship_tags.py b/symposion_project/apps/sponsorship/templatetags/sponsorship_tags.py index baae404b..1c59be41 100644 --- a/symposion_project/apps/sponsorship/templatetags/sponsorship_tags.py +++ b/symposion_project/apps/sponsorship/templatetags/sponsorship_tags.py @@ -1,6 +1,6 @@ from django import template -from sponsorship.models import Sponsor +from sponsorship.models import Sponsor, SponsorLevel register = template.Library() @@ -11,33 +11,62 @@ class SponsorsNode(template.Node): @classmethod def handle_token(cls, parser, token): bits = token.split_contents() - if len(bits) != 4: - raise template.TemplateSyntaxError("%r takes exactly three arguments " - "(second argument must be 'as')" % bits[0]) - if bits[2] != "as": - raise template.TemplateSyntaxError("Second argument to %r must be " - "'as'" % bits[0]) - return cls(bits[1], bits[3]) + if len(bits) == 3 and bits[1] == "as": + return cls(bits[2]) + elif len(bits) == 4 and bits[2] == "as": + return cls(bits[3], bits[1]) + else: + raise template.TemplateSyntaxError("%r takes 'as var' or 'level as var'" % bits[0]) - def __init__(self, level, context_var): - self.level = template.Variable(level) + def __init__(self, context_var, level=None): + if level: + self.level = template.Variable(level) + else: + self.level = None self.context_var = context_var def render(self, context): - level = self.level.resolve(context) - queryset = Sponsor.objects.filter( - level__name__iexact = level, - active = True - ).order_by( - "added" - ) + if self.level: + level = self.level.resolve(context) + queryset = Sponsor.objects.filter(level__name__iexact = level, active = True).order_by("added") + else: + queryset = Sponsor.objects.filter(active = True).order_by("level__order", "added") context[self.context_var] = queryset return u"" +class SponsorLevelNode(template.Node): + + @classmethod + def handle_token(cls, parser, token): + bits = token.split_contents() + if len(bits) == 3 and bits[1] == "as": + return cls(bits[2]) + else: + raise template.TemplateSyntaxError("%r takes 'as var'" % bits[0]) + + def __init__(self, context_var): + self.context_var = context_var + + def render(self, context): + context[self.context_var] = SponsorLevel.objects.all() + return u"" + + @register.tag def sponsors(parser, token): """ - {% sponsors "gold" as sponsors %} + {% sponsors as all_sponsors %} + or + {% sponsors "gold" as gold_sponsors %} """ return SponsorsNode.handle_token(parser, token) + + +@register.tag +def sponsor_levels(parser, token): + """ + {% sponsor_levels as levels %} + """ + return SponsorLevelNode.handle_token(parser, token) + \ No newline at end of file diff --git a/symposion_project/requirements/project.txt b/symposion_project/requirements/project.txt index 6d8b1485..0d0fa5f3 100644 --- a/symposion_project/requirements/project.txt +++ b/symposion_project/requirements/project.txt @@ -4,4 +4,7 @@ --requirement=base.txt # Put project-specific requirements here. -# See http://pip-installer.org/requirement-format.html for more information. \ No newline at end of file +# See http://pip-installer.org/requirement-format.html for more information. + +PIL==1.1.7 +easy-thumbnails==1.0-alpha-21 diff --git a/symposion_project/settings.py b/symposion_project/settings.py index c84b830a..4bef98ec 100644 --- a/symposion_project/settings.py +++ b/symposion_project/settings.py @@ -157,6 +157,7 @@ INSTALLED_APPS = [ "timezones", "emailconfirmation", "metron", + "easy_thumbnails", # Pinax "pinax.apps.account", @@ -164,6 +165,7 @@ INSTALLED_APPS = [ # project "about", + "sponsorship", ] FIXTURE_DIRS = [ diff --git a/symposion_project/templates/sponsorship/_horizontal_by_level.html b/symposion_project/templates/sponsorship/_horizontal_by_level.html new file mode 100644 index 00000000..98025053 --- /dev/null +++ b/symposion_project/templates/sponsorship/_horizontal_by_level.html @@ -0,0 +1,11 @@ +{% load sponsorship_tags %} +{% sponsor_levels as levels %} + diff --git a/symposion_project/templates/sponsorship/_sponsor_link.html b/symposion_project/templates/sponsorship/_sponsor_link.html new file mode 100644 index 00000000..39d9aade --- /dev/null +++ b/symposion_project/templates/sponsorship/_sponsor_link.html @@ -0,0 +1,10 @@ +{% load thumbnail %} +{% spaceless %} + + {% if dimensions %} + {{ sponsor.name }} + {% else %} + {{ sponsor.name }} + {% endif %} + +{% endspaceless %} diff --git a/symposion_project/templates/sponsorship/_vertical_by_level.html b/symposion_project/templates/sponsorship/_vertical_by_level.html new file mode 100644 index 00000000..b2ed5ec4 --- /dev/null +++ b/symposion_project/templates/sponsorship/_vertical_by_level.html @@ -0,0 +1,13 @@ +{% load sponsorship_tags %} +{% sponsor_levels as levels %} + diff --git a/symposion_project/templates/sponsorship/_wall.html b/symposion_project/templates/sponsorship/_wall.html new file mode 100644 index 00000000..7f1b9896 --- /dev/null +++ b/symposion_project/templates/sponsorship/_wall.html @@ -0,0 +1,7 @@ +{% load sponsorship_tags %} +{% sponsors as sponsors %} + From 3d6a69466b57b9cd32e6cea605a9d62d7fb44699 Mon Sep 17 00:00:00 2001 From: James Tauber Date: Sun, 5 Feb 2012 18:18:30 -0500 Subject: [PATCH 4/6] initial documentation of sponsorship app --- symposion_project/docs/index.rst | 5 +- symposion_project/docs/sponsorship.rst | 82 ++++++++++++++++++++++++++ 2 files changed, 85 insertions(+), 2 deletions(-) create mode 100644 symposion_project/docs/sponsorship.rst diff --git a/symposion_project/docs/index.rst b/symposion_project/docs/index.rst index af2535e8..ec72ecbc 100644 --- a/symposion_project/docs/index.rst +++ b/symposion_project/docs/index.rst @@ -10,11 +10,12 @@ We are in the process of cleaning things up and making them more generic. The project homepage is http://pinax.github.com/symposion/ -Contents: +Apps: .. toctree:: :maxdepth: 2 - + + sponsorship Indices and tables diff --git a/symposion_project/docs/sponsorship.rst b/symposion_project/docs/sponsorship.rst new file mode 100644 index 00000000..5907a1a3 --- /dev/null +++ b/symposion_project/docs/sponsorship.rst @@ -0,0 +1,82 @@ +Sponsorship App +=============== + +Sponsorship is managed via the ``sponsorship`` app. + +Sponsorship levels and sponsors are added via the Django admin. + + +Models +------ + +Each sponsor level has a ``name`` (e.g. "Gold", "Silver") and an ``order`` +field which is an integer that is used to sort levels (lowest first). Each +level also has a ``description`` which is not currently exposed anywhere +but can be used for private annotation. + +Each sponsor has a ``name``, ``external_url`` (i.e. link to the sponsor's +website), ``contact_name`` and ``contact_email``, ``logo``, and ``level``. + +A sponsor may also have a private ``annotation`` that can be used by +organizers to take notes about the sponsor. + +A sponsor will not appear on the site until the ``active`` flag is set true. + + +Template Snippets +----------------- + +The easiest way to include sponsor logos, grouped by level, is to either:: + + {% include "sponsorship/_vertical_by_level.html" %} + +or:: + + {% include "sponsorship/_horizontal_by_level.html" %} + +You can get a wall of sponsors (without level designation) with:: + + {% include "sponsorship/_wall.html" %} + + +You can always tweak these templates or use them as the basis for your own. +This is often all you'll need to do to display sponsors on your site. + +If you want to display a specific sponsor logo you can use:: + + {% include "sponsorship/_sponsor_link.html" with sponsor=sponsor %} + +or:: + + {% include "sponsorship/_sponsor_link.html" with sponsor=sponsor dimensions="100x100" %} + +if you want different dimensions than the default 150 x 150. + + +Template Tags +------------- + +If you want to retrieve the sponsors and traverse them yourself, you can use +the provided template tags:: + + {% load sponsorship_tags %} + + {% sponsors as all_sponsors %} + +or:: + + {% load sponsorship_tags %} + + {% sponsors "Gold" as gold_sponsors %} + +if you want to just get a specific level. + + +You can get the levels with:: + + {% load sponsorship_tags %} + + {% sponsor_levels as levels %} + +and you can always iterate over those levels, calling ``level.sponsors`` to +get the sponsors at that level. From ef2624698b3c3511f72a4333fa40aac12a22996b Mon Sep 17 00:00:00 2001 From: James Tauber Date: Sun, 5 Feb 2012 22:50:47 -0500 Subject: [PATCH 5/6] made sponsorship app conference-aware --- symposion_project/apps/sponsorship/admin.py | 2 +- symposion_project/apps/sponsorship/models.py | 7 +++++-- .../apps/sponsorship/templatetags/sponsorship_tags.py | 9 ++++++--- 3 files changed, 12 insertions(+), 6 deletions(-) diff --git a/symposion_project/apps/sponsorship/admin.py b/symposion_project/apps/sponsorship/admin.py index e234e794..6814c4da 100644 --- a/symposion_project/apps/sponsorship/admin.py +++ b/symposion_project/apps/sponsorship/admin.py @@ -3,5 +3,5 @@ from django.contrib import admin from sponsorship.models import SponsorLevel, Sponsor -admin.site.register(SponsorLevel, list_display=("order", "name")) +admin.site.register(SponsorLevel) admin.site.register(Sponsor, list_display=("name", "level", "added", "active"), list_filter = ("level", )) diff --git a/symposion_project/apps/sponsorship/models.py b/symposion_project/apps/sponsorship/models.py index f77de766..564314db 100644 --- a/symposion_project/apps/sponsorship/models.py +++ b/symposion_project/apps/sponsorship/models.py @@ -2,18 +2,21 @@ import datetime from django.db import models +from conference.models import Conference + class SponsorLevel(models.Model): + conference = models.ForeignKey(Conference) name = models.CharField(max_length=100) order = models.IntegerField(default=0) description = models.TextField(blank=True) class Meta: - ordering = ["order"] + ordering = ["conference", "order"] def __unicode__(self): - return self.name + return u"%s %s" % (self.conference, self.name) def sponsors(self): return self.sponsor_set.filter(active=True).order_by("added") diff --git a/symposion_project/apps/sponsorship/templatetags/sponsorship_tags.py b/symposion_project/apps/sponsorship/templatetags/sponsorship_tags.py index 1c59be41..00fb8139 100644 --- a/symposion_project/apps/sponsorship/templatetags/sponsorship_tags.py +++ b/symposion_project/apps/sponsorship/templatetags/sponsorship_tags.py @@ -1,5 +1,6 @@ from django import template +from conference.models import current_conference from sponsorship.models import Sponsor, SponsorLevel @@ -26,11 +27,12 @@ class SponsorsNode(template.Node): self.context_var = context_var def render(self, context): + conference = current_conference() if self.level: level = self.level.resolve(context) - queryset = Sponsor.objects.filter(level__name__iexact = level, active = True).order_by("added") + queryset = Sponsor.objects.filter(level__conference = conference, level__name__iexact = level, active = True).order_by("added") else: - queryset = Sponsor.objects.filter(active = True).order_by("level__order", "added") + queryset = Sponsor.objects.filter(level__conference = conference, active = True).order_by("level__order", "added") context[self.context_var] = queryset return u"" @@ -49,7 +51,8 @@ class SponsorLevelNode(template.Node): self.context_var = context_var def render(self, context): - context[self.context_var] = SponsorLevel.objects.all() + conference = current_conference() + context[self.context_var] = SponsorLevel.objects.filter(conference=conference) return u"" From de0cf9f1631745f05f0e2f06964f3f8b93cf5729 Mon Sep 17 00:00:00 2001 From: James Tauber Date: Wed, 22 Feb 2012 17:35:21 -0500 Subject: [PATCH 6/6] internationalized the sponsor model fields --- symposion_project/apps/sponsorship/models.py | 33 ++++++++++++-------- 1 file changed, 20 insertions(+), 13 deletions(-) diff --git a/symposion_project/apps/sponsorship/models.py b/symposion_project/apps/sponsorship/models.py index 564314db..07d0cb30 100644 --- a/symposion_project/apps/sponsorship/models.py +++ b/symposion_project/apps/sponsorship/models.py @@ -1,19 +1,22 @@ import datetime from django.db import models +from django.utils.translation import ugettext_lazy as _ from conference.models import Conference class SponsorLevel(models.Model): - conference = models.ForeignKey(Conference) - name = models.CharField(max_length=100) - order = models.IntegerField(default=0) - description = models.TextField(blank=True) + conference = models.ForeignKey(Conference, verbose_name=_("conference")) + name = models.CharField(_("name"), max_length=100) + order = models.IntegerField(_("order"), default=0) + description = models.TextField(_("description"), blank=True) class Meta: ordering = ["conference", "order"] + verbose_name = _("sponsor level") + verbose_name_plural = _("sponsor levels") def __unicode__(self): return u"%s %s" % (self.conference, self.name) @@ -24,15 +27,19 @@ class SponsorLevel(models.Model): class Sponsor(models.Model): - name = models.CharField(max_length=100) - external_url = models.URLField("external URL") - annotation = models.TextField(blank=True) - contact_name = models.CharField(max_length=100) - contact_email = models.EmailField(u"Contact e\u2011mail") - logo = models.ImageField(upload_to="sponsor_logos/") - level = models.ForeignKey(SponsorLevel) - added = models.DateTimeField(default=datetime.datetime.now) - active = models.BooleanField(default=False) + name = models.CharField(_("name"), max_length=100) + external_url = models.URLField(_("external URL")) + annotation = models.TextField(_("annotation"), blank=True) + contact_name = models.CharField(_("contact_name"), max_length=100) + contact_email = models.EmailField(_(u"Contact e\u2011mail")) + logo = models.ImageField(_("logo"), upload_to="sponsor_logos/") + level = models.ForeignKey(SponsorLevel, verbose_name=_("level")) + added = models.DateTimeField(_("added"), default=datetime.datetime.now) + active = models.BooleanField(_("active"), default=False) def __unicode__(self): return self.name + + class Meta: + verbose_name = _("sponsor") + verbose_name_plural = _("sponsors")