remove pycon folder, as we've transplanted sponsors

This commit is contained in:
Luke Hatcher 2012-07-13 20:36:55 -04:00
parent 64fdf5147c
commit 53dfff3315
18 changed files with 0 additions and 939 deletions

View file

View file

@ -1,8 +0,0 @@
from django.contrib import admin
from pycon.models import PyConProposalCategory, PyConTalkProposal, PyConTutorialProposal, PyConPosterProposal
admin.site.register(PyConProposalCategory)
admin.site.register(PyConTalkProposal)
admin.site.register(PyConTutorialProposal)
admin.site.register(PyConPosterProposal)

View file

@ -1,84 +0,0 @@
from django import forms
from markitup.widgets import MarkItUpWidget
from pycon.models import PyConProposalCategory, PyConTalkProposal, PyConTutorialProposal, PyConPosterProposal
class PyConProposalForm(forms.ModelForm):
def __init__(self, *args, **kwargs):
super(PyConProposalForm, self).__init__(*args, **kwargs)
self.fields["category"] = forms.ModelChoiceField(
queryset = PyConProposalCategory.objects.order_by("name")
)
def clean_description(self):
value = self.cleaned_data["description"]
if len(value) > 400:
raise forms.ValidationError(
u"The description must be less than 400 characters"
)
return value
class PyConTalkProposalForm(PyConProposalForm):
class Meta:
model = PyConTalkProposal
fields = [
"title",
"category",
"audience_level",
"extreme",
"duration",
"description",
"abstract",
"additional_notes",
"recording_release",
]
widgets = {
"abstract": MarkItUpWidget(),
"additional_notes": MarkItUpWidget(),
}
class PyConTutorialProposalForm(PyConProposalForm):
class Meta:
model = PyConTutorialProposal
fields = [
"title",
"category",
"audience_level",
"description",
"abstract",
"additional_notes",
"recording_release",
]
widgets = {
"abstract": MarkItUpWidget(),
"additional_notes": MarkItUpWidget(),
}
class PyConPosterProposalForm(PyConProposalForm):
class Meta:
model = PyConPosterProposal
fields = [
"title",
"category",
"audience_level",
"description",
"abstract",
"additional_notes",
"recording_release",
]
widgets = {
"abstract": MarkItUpWidget(),
"additional_notes": MarkItUpWidget(),
}

View file

@ -1,68 +0,0 @@
from django.db import models
from symposion.proposals.models import ProposalBase
class PyConProposalCategory(models.Model):
name = models.CharField(max_length=100)
slug = models.SlugField()
def __unicode__(self):
return self.name
class Meta:
verbose_name = "PyCon proposal category"
verbose_name_plural = "PyCon proposal categories"
class PyConProposal(ProposalBase):
AUDIENCE_LEVEL_NOVICE = 1
AUDIENCE_LEVEL_EXPERIENCED = 2
AUDIENCE_LEVEL_INTERMEDIATE = 3
AUDIENCE_LEVELS = [
(AUDIENCE_LEVEL_NOVICE, "Novice"),
(AUDIENCE_LEVEL_INTERMEDIATE, "Intermediate"),
(AUDIENCE_LEVEL_EXPERIENCED, "Experienced"),
]
category = models.ForeignKey(PyConProposalCategory)
audience_level = models.IntegerField(choices=AUDIENCE_LEVELS)
recording_release = models.BooleanField(
default=True,
help_text="By submitting your talk proposal, you agree to give permission to the Python Software Foundation to record, edit, and release audio and/or video of your presentation. If you do not agree to this, please uncheck this box. See <a href='https://us.pycon.org/2013/speaking/recording/' target='_blank'>PyCon 2013 Recording Release</a> for details."
)
class Meta:
abstract = True
class PyConTalkProposal(PyConProposal):
DURATION_CHOICES = [
(0, "No preference"),
(1, "I prefer a 30 minute slot"),
(2, "I prefer a 45 minute slot"),
]
extreme = models.BooleanField(
default=False,
help_text="'Extreme' talks are advanced talks with little or no introductory material. See <a href='http://us.pycon.org/2013/speaker/extreme/' target='_blank'>Extreme Talks</a> for details."
)
duration = models.IntegerField(choices=DURATION_CHOICES)
class Meta:
verbose_name = "PyCon talk proposal"
class PyConTutorialProposal(PyConProposal):
class Meta:
verbose_name = "PyCon tutorial proposal"
class PyConPosterProposal(PyConProposal):
class Meta:
verbose_name = "PyCon poster proposal"

View file

@ -1,5 +0,0 @@
SPONSOR_COORDINATORS = "sponsor-coordinators"
AUTH_GROUPS = [
SPONSOR_COORDINATORS
]

View file

@ -1,69 +0,0 @@
from django.contrib import admin
from pycon.sponsorship.models import SponsorLevel, Sponsor, Benefit, BenefitLevel, SponsorBenefit
class BenefitLevelInline(admin.TabularInline):
model = BenefitLevel
extra = 0
class SponsorBenefitInline(admin.StackedInline):
model = SponsorBenefit
extra = 0
fieldsets = [
(None, {
"fields": [
("benefit", "active"),
("max_words", "other_limits"),
"text",
"upload",
]
})
]
class SponsorAdmin(admin.ModelAdmin):
save_on_top = True
fieldsets = [
(None, {
"fields": [
("name", "applicant"),
("level", "active"),
"external_url",
"annotation",
("contact_name", "contact_email")
]
}),
("Metadata", {
"fields": ["added"],
"classes": ["collapse"]
})
]
inlines = [SponsorBenefitInline]
def get_form(self, *args, **kwargs):
# @@@ kinda ugly but using choices= on NullBooleanField is broken
form = super(SponsorAdmin, self).get_form(*args, **kwargs)
form.base_fields["active"].widget.choices = [
(u"1", "unreviewed"),
(u"2", "approved"),
(u"3", "rejected")
]
return form
class BenefitAdmin(admin.ModelAdmin):
inlines = [BenefitLevelInline]
class SponsorLevelAdmin(admin.ModelAdmin):
inlines = [BenefitLevelInline]
admin.site.register(SponsorLevel, SponsorLevelAdmin)
admin.site.register(Sponsor, SponsorAdmin)
admin.site.register(Benefit, BenefitAdmin)

View file

@ -1,72 +0,0 @@
from django import forms
from django.forms.models import inlineformset_factory, BaseInlineFormSet
from django.contrib.admin.widgets import AdminFileWidget
from pycon.sponsorship.models import Sponsor, SponsorBenefit
class SponsorApplicationForm(forms.ModelForm):
def __init__(self, *args, **kwargs):
self.user = kwargs.pop("user")
kwargs.update({
"initial": {
"contact_name": self.user.get_full_name,
"contact_email": self.user.email,
}
})
super(SponsorApplicationForm, self).__init__(*args, **kwargs)
class Meta:
model = Sponsor
fields = ["name", "contact_name", "contact_email", "level"]
def save(self, commit=True):
obj = super(SponsorApplicationForm, self).save(commit=False)
obj.applicant = self.user
if commit:
obj.save()
return obj
class SponsorDetailsForm(forms.ModelForm):
class Meta:
model = Sponsor
fields = [
"name",
"external_url",
"contact_name",
"contact_email"
]
class SponsorBenefitsInlineFormSet(BaseInlineFormSet):
def _construct_form(self, i, **kwargs):
form = super(SponsorBenefitsInlineFormSet, self)._construct_form(i, **kwargs)
# only include the relevant data fields for this benefit type
fields = form.instance.data_fields()
form.fields = dict((k, v) for (k, v) in form.fields.items() if k in fields + ["id"])
for field in fields:
# don't need a label, the form template will label it with the benefit name
form.fields[field].label = ""
# provide word limit as help_text
if form.instance.benefit.type == "text" and form.instance.max_words:
form.fields[field].help_text = u"maximum %s words" % form.instance.max_words
# use admin file widget that shows currently uploaded file
if field == "upload":
form.fields[field].widget = AdminFileWidget()
return form
SponsorBenefitsFormSet = inlineformset_factory(
Sponsor, SponsorBenefit,
formset=SponsorBenefitsInlineFormSet,
can_delete=False, extra=0,
fields=["text", "upload"]
)

View file

@ -1,12 +0,0 @@
from django.core.management.base import BaseCommand
from django.contrib.auth.models import Group
from pycon.sponsorship import AUTH_GROUPS
class Command(BaseCommand):
def handle(self, *args, **options):
for group in AUTH_GROUPS:
Group.objects.get_or_create(name=group)

View file

@ -1,80 +0,0 @@
import csv
import os
import shutil
import zipfile
from contextlib import closing
from django.core.management.base import BaseCommand, CommandError
from django.template.defaultfilters import slugify
from pycon.sponsorship.models import Sponsor
def zipdir(basedir, archivename):
assert os.path.isdir(basedir)
with closing(zipfile.ZipFile(archivename, "w", zipfile.ZIP_DEFLATED)) as z:
for root, dirs, files in os.walk(basedir):
#NOTE: ignore empty directories
for fn in files:
absfn = os.path.join(root, fn)
zfn = absfn[len(basedir)+len(os.sep):] #XXX: relative path
z.write(absfn, zfn)
class Command(BaseCommand):
def handle(self, *args, **options):
try:
os.makedirs(os.path.join(os.getcwd(), "build"))
except:
pass
csv_file = csv.writer(
open(os.path.join(os.getcwd(), "build", "sponsors.csv"), "wb")
)
csv_file.writerow(["Name", "URL", "Level", "Description"])
for sponsor in Sponsor.objects.all():
path = os.path.join(os.getcwd(), "build", slugify(sponsor.name))
try:
os.makedirs(path)
except:
pass
data = {
"name": sponsor.name,
"url": sponsor.external_url,
"level": sponsor.level.name,
"description": "",
}
for sponsor_benefit in sponsor.sponsor_benefits.all():
if sponsor_benefit.benefit_id == 2:
data["description"] = sponsor_benefit.text
if sponsor_benefit.benefit_id == 1:
if sponsor_benefit.upload:
data["ad"] = sponsor_benefit.upload.path
if sponsor_benefit.benefit_id == 7:
if sponsor_benefit.upload:
data["logo"] = sponsor_benefit.upload.path
if "ad" in data:
ad_path = data.pop("ad")
shutil.copy(ad_path, path)
if "logo" in data:
logo_path = data.pop("logo")
shutil.copy(logo_path, path)
csv_file.writerow([
data["name"].encode("utf-8"),
data["url"].encode("utf-8"),
data["level"].encode("utf-8"),
data["description"].encode("utf-8")
])
zipdir(
os.path.join(
os.getcwd(), "build"),
os.path.join(os.getcwd(), "sponsors.zip"
)
)

View file

@ -1,38 +0,0 @@
from django.core.management.base import BaseCommand
from django.contrib.auth.models import Group
from pycon.sponsorship.models import Sponsor, SponsorBenefit
class Command(BaseCommand):
def handle(self, *args, **options):
for sponsor in Sponsor.objects.all():
level = None
try:
level = sponsor.level
except SponsorLevel.DoesNotExist:
pass
if level:
for benefit_level in level.benefit_levels.all():
# Create all needed benefits if they don't exist already
sponsor_benefit, created = SponsorBenefit.objects.get_or_create(
sponsor=sponsor, benefit=benefit_level.benefit)
if created:
print "created", sponsor_benefit, "for", sponsor
# and set to default limits for this level.
sponsor_benefit.max_words = benefit_level.max_words
sponsor_benefit.other_limits = benefit_level.other_limits
# and set to active
sponsor_benefit.active = True
# @@@ We don't call sponsor_benefit.clean here. This means
# that if the sponsorship level for a sponsor is adjusted
# downwards, an existing too-long text entry can remain,
# and won't raise a validation error until it's next
# edited.
sponsor_benefit.save()

View file

@ -1,38 +0,0 @@
from django.db import models
class SponsorManager(models.Manager):
def active(self):
return self.get_query_set().filter(active=True).order_by("level")
def with_weblogo(self):
queryset = self.raw("""
SELECT DISTINCT
"sponsorship_sponsor"."id",
"sponsorship_sponsor"."applicant_id",
"sponsorship_sponsor"."name",
"sponsorship_sponsor"."external_url",
"sponsorship_sponsor"."annotation",
"sponsorship_sponsor"."contact_name",
"sponsorship_sponsor"."contact_email",
"sponsorship_sponsor"."level_id",
"sponsorship_sponsor"."added",
"sponsorship_sponsor"."active",
"sponsorship_sponsorlevel"."order"
FROM
"sponsorship_sponsor"
INNER JOIN
"sponsorship_sponsorbenefit" ON ("sponsorship_sponsor"."id" = "sponsorship_sponsorbenefit"."sponsor_id")
INNER JOIN
"sponsorship_benefit" ON ("sponsorship_sponsorbenefit"."benefit_id" = "sponsorship_benefit"."id")
LEFT OUTER JOIN
"sponsorship_sponsorlevel" ON ("sponsorship_sponsor"."level_id" = "sponsorship_sponsorlevel"."id")
WHERE (
"sponsorship_sponsor"."active" = 't' AND
"sponsorship_benefit"."type" = 'weblogo' AND
"sponsorship_sponsorbenefit"."upload" != ''
)
ORDER BY "sponsorship_sponsorlevel"."order" ASC, "sponsorship_sponsor"."added" ASC
""")
return queryset

View file

@ -1,266 +0,0 @@
import datetime
from django.core.exceptions import ValidationError
from django.core.urlresolvers import reverse
from django.db import models
from django.db.models.signals import post_init, post_save
from django.utils.translation import ugettext_lazy as _
from django.contrib.auth.models import User
from symposion.conference.models import Conference
from pycon.sponsorship import SPONSOR_COORDINATORS
from pycon.sponsorship.managers import SponsorManager
# from symposion.utils.mail import send_email
class SponsorLevel(models.Model):
conference = models.ForeignKey(Conference, verbose_name=_("conference"))
name = models.CharField(_("name"), max_length=100)
order = models.IntegerField(_("order"), default=0)
cost = models.PositiveIntegerField(_("cost"))
description = models.TextField(_("description"), blank=True, help_text=_("This is private."))
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)
def sponsors(self):
return self.sponsor_set.filter(active=True).order_by("added")
class Sponsor(models.Model):
applicant = models.ForeignKey(User, related_name="sponsorships", verbose_name=_("applicant"), null=True)
name = models.CharField(_("Sponsor 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 Email"))
level = models.ForeignKey(SponsorLevel, verbose_name=_("level"))
added = models.DateTimeField(_("added"), default=datetime.datetime.now)
active = models.BooleanField(_("active"), default=False)
# Denormalization (this assumes only one logo)
sponsor_logo = models.ForeignKey("SponsorBenefit", related_name="+", null=True, blank=True, editable=False)
objects = SponsorManager()
def __unicode__(self):
return self.name
class Meta:
verbose_name = _("sponsor")
verbose_name_plural = _("sponsors")
def get_absolute_url(self):
if self.active:
return reverse("sponsor_detail", kwargs={"pk": self.pk})
return reverse("sponsor_list")
@property
def website_logo_url(self):
if not hasattr(self, "_website_logo_url"):
self._website_logo_url = None
benefits = self.sponsor_benefits.filter(benefit__type="weblogo", upload__isnull=False)
if benefits.exists():
# @@@ smarter handling of multiple weblogo benefits?
# shouldn't happen
if benefits[0].upload:
self._website_logo_url = benefits[0].upload.url
return self._website_logo_url
@property
def listing_text(self):
if not hasattr(self, "_listing_text"):
self._listing_text = None
benefits = self.sponsor_benefits.filter(benefit__id=7)
if benefits.count():
self._listing_text = benefits[0].text
return self._listing_text
@property
def joblisting_text(self):
if not hasattr(self, "_joblisting_text"):
self._joblisting_text = None
benefits = self.sponsor_benefits.filter(benefit__id=21)
if benefits.count():
self._joblisting_text = benefits[0].text
return self._joblisting_text
@property
def website_logo(self):
if self.sponsor_logo is None:
benefits = self.sponsor_benefits.filter(benefit__type="weblogo", upload__isnull=False)[:1]
if benefits.count():
if benefits[0].upload:
self.sponsor_logo = benefits[0]
self.save()
return self.sponsor_logo.upload
def reset_benefits(self):
"""
Reset all benefits for this sponsor to the defaults for their
sponsorship level.
"""
level = None
try:
level = self.level
except SponsorLevel.DoesNotExist:
pass
allowed_benefits = []
if level:
for benefit_level in level.benefit_levels.all():
# Create all needed benefits if they don't exist already
sponsor_benefit, created = SponsorBenefit.objects.get_or_create(
sponsor=self, benefit=benefit_level.benefit)
# and set to default limits for this level.
sponsor_benefit.max_words = benefit_level.max_words
sponsor_benefit.other_limits = benefit_level.other_limits
# and set to active
sponsor_benefit.active = True
# @@@ We don't call sponsor_benefit.clean here. This means
# that if the sponsorship level for a sponsor is adjusted
# downwards, an existing too-long text entry can remain,
# and won't raise a validation error until it's next
# edited.
sponsor_benefit.save()
allowed_benefits.append(sponsor_benefit.pk)
# Any remaining sponsor benefits that don't normally belong to
# this level are set to inactive
self.sponsor_benefits.exclude(pk__in=allowed_benefits).update(active=False, max_words=None, other_limits="")
# @@@ should this just be done centrally?
def send_coordinator_emails(self):
for user in User.objects.filter(groups__name=SPONSOR_COORDINATORS):
send_email(
[user.email], "sponsor_signup",
context = {"sponsor": self}
)
def _store_initial_level(sender, instance, **kwargs):
if instance:
instance._initial_level_id = instance.level_id
post_init.connect(_store_initial_level, sender=Sponsor)
def _check_level_change(sender, instance, created, **kwargs):
if instance and (created or instance.level_id != instance._initial_level_id):
instance.reset_benefits()
post_save.connect(_check_level_change, sender=Sponsor)
def _send_sponsor_notification_emails(sender, instance, created, **kwargs):
if instance and created:
instance.send_coordinator_emails()
post_save.connect(_send_sponsor_notification_emails, sender=Sponsor)
class Benefit(models.Model):
name = models.CharField(_("name"), max_length=100)
description = models.TextField(_("description"), blank=True)
type = models.CharField(
_("type"),
choices=[
("text", "Text"),
("file", "File"),
("weblogo", "Web Logo"),
("simple", "Simple")
],
max_length=10,
default="simple"
)
def __unicode__(self):
return self.name
class BenefitLevel(models.Model):
benefit = models.ForeignKey(
Benefit,
related_name="benefit_levels",
verbose_name=_("benefit")
)
level = models.ForeignKey(
SponsorLevel,
related_name="benefit_levels",
verbose_name=_("level")
)
max_words = models.PositiveIntegerField(_("max words"), blank=True, null=True)
other_limits = models.CharField(_("other limits"), max_length=200, blank=True)
class Meta:
ordering = ["level"]
def __unicode__(self):
return u"%s - %s" % (self.level, self.benefit)
class SponsorBenefit(models.Model):
sponsor = models.ForeignKey(
Sponsor,
related_name="sponsor_benefits",
verbose_name=_("sponsor")
)
benefit = models.ForeignKey(Benefit,
related_name="sponsor_benefits",
verbose_name=_("benefit")
)
active = models.BooleanField(default=True)
# Limits: will initially be set to defaults from corresponding BenefitLevel
max_words = models.PositiveIntegerField(_("max words"), blank=True, null=True)
other_limits = models.CharField(_("other limits"), max_length=200, blank=True)
# Data: zero or one of these fields will be used, depending on the
# type of the Benefit (text, file, or simple)
text = models.TextField(_("text"), blank=True)
upload = models.FileField(_("file"), blank=True, upload_to="sponsor_files")
class Meta:
ordering = ['-active']
def __unicode__(self):
return u"%s - %s" % (self.sponsor, self.benefit)
def clean(self):
if self.max_words and len(self.text.split()) > self.max_words:
raise ValidationError("Sponsorship level only allows for %s words." % self.max_words)
def data_fields(self):
"""
Return list of data field names which should be editable for
this ``SponsorBenefit``, depending on its ``Benefit`` type.
"""
if self.benefit.type == "file" or self.benefit.type == "weblogo":
return ["upload"]
elif self.benefit.type == "text":
return ["text"]
return []
def _denorm_weblogo(sender, instance, created, **kwargs):
if instance:
if instance.benefit.type == "weblogo" and instance.upload:
sponsor = instance.sponsor
sponsor.sponsor_logo = instance
sponsor.save()
post_save.connect(_denorm_weblogo, sender=SponsorBenefit)

View file

@ -1,74 +0,0 @@
from django import template
from symposion.conference.models import current_conference
from pycon.sponsorship.models import Sponsor, SponsorLevel
register = template.Library()
class SponsorsNode(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])
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, context_var, level=None):
if level:
self.level = template.Variable(level)
else:
self.level = None
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__conference = conference, level__name__iexact = level, active = True).order_by("added")
else:
queryset = Sponsor.objects.filter(level__conference = conference, 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):
conference = current_conference()
context[self.context_var] = SponsorLevel.objects.filter(conference=conference)
return u""
@register.tag
def sponsors(parser, token):
"""
{% 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)

View file

@ -1,10 +0,0 @@
from django.conf.urls.defaults import patterns, url
from django.views.generic.simple import direct_to_template
urlpatterns = patterns("pycon.sponsorship.views",
url(r"^$", direct_to_template, {"template": "sponsorship/list.html"}, name="sponsor_list"),
# url(r"^jobs/$", direct_to_template, {"template": "sponsors/jobs.html"}, name="sponsor_jobs"),
url(r"^apply/$", "sponsor_apply", name="sponsor_apply"),
url(r"^(?P<pk>\d+)/$", "sponsor_detail", name="sponsor_detail"),
)

View file

@ -1,115 +0,0 @@
import itertools
from functools import wraps
from django.http import HttpResponse
from django.shortcuts import render_to_response, redirect, get_object_or_404
from django.template import RequestContext
from django.contrib import messages
from django.contrib.admin.views.decorators import staff_member_required
from django.contrib.auth.decorators import login_required
from pycon.sponsorship.forms import SponsorApplicationForm, SponsorDetailsForm, SponsorBenefitsFormSet
from pycon.sponsorship.models import Sponsor, SponsorBenefit
@login_required
def sponsor_apply(request):
if request.method == "POST":
form = SponsorApplicationForm(request.POST, user=request.user)
if form.is_valid():
form.save()
return redirect("dashboard")
else:
form = SponsorApplicationForm(user=request.user)
return render_to_response("sponsorship/apply.html", {
"form": form,
}, context_instance=RequestContext(request))
@login_required
def sponsor_detail(request, pk):
sponsor = get_object_or_404(Sponsor, pk=pk)
if not sponsor.active or sponsor.applicant != request.user:
return redirect("sponsor_list")
formset_kwargs = {
"instance": sponsor,
"queryset": SponsorBenefit.objects.filter(active=True)
}
if request.method == "POST":
form = SponsorDetailsForm(request.POST, instance=sponsor)
formset = SponsorBenefitsFormSet(request.POST, request.FILES, **formset_kwargs)
if form.is_valid() and formset.is_valid():
form.save()
formset.save()
messages.success(request, "Your sponsorship application has been submitted!")
return redirect(request.path)
else:
form = SponsorDetailsForm(instance=sponsor)
formset = SponsorBenefitsFormSet(**formset_kwargs)
return render_to_response("sponsorship/detail.html", {
"sponsor": sponsor,
"form": form,
"formset": formset,
}, context_instance=RequestContext(request))
@staff_member_required
def sponsor_export_data(request):
sponsors = []
data = ""
for sponsor in Sponsor.objects.order_by("added"):
d = {
"name": sponsor.name,
"url": sponsor.external_url,
"level": (sponsor.level.order, sponsor.level.name),
"description": "",
}
for sponsor_benefit in sponsor.sponsor_benefits.all():
if sponsor_benefit.benefit_id == 2:
d["description"] = sponsor_benefit.text
sponsors.append(d)
def izip_longest(*args):
fv = None
def sentinel(counter=([fv]*(len(args)-1)).pop):
yield counter()
iters = [itertools.chain(it, sentinel(), itertools.repeat(fv)) for it in args]
try:
for tup in itertools.izip(*iters):
yield tup
except IndexError:
pass
def pairwise(iterable):
a, b = itertools.tee(iterable)
b.next()
return izip_longest(a, b)
def level_key(s):
return s["level"]
for level, level_sponsors in itertools.groupby(sorted(sponsors, key=level_key), level_key):
data += "%s\n" % ("-" * (len(level[1])+4))
data += "| %s |\n" % level[1]
data += "%s\n\n" % ("-" * (len(level[1])+4))
for sponsor, next in pairwise(level_sponsors):
description = sponsor["description"].strip()
description = description if description else "-- NO DESCRIPTION FOR THIS SPONSOR --"
data += "%s\n\n%s" % (sponsor["name"], description)
if next is not None:
data += "\n\n%s\n\n" % ("-"*80)
else:
data += "\n\n"
return HttpResponse(data, content_type="text/plain;charset=utf-8")