Skip to content
Browse files

added simple json-based import of subscribers

  • Loading branch information...
1 parent 8eeb879 commit db46aae3eb3b48a55e02615b1e7c171d31f29294 @arneb arneb committed Feb 20, 2009
Showing with 150 additions and 6 deletions.
  1. +86 −4 campaign/admin.py
  2. +19 −0 campaign/forms.py
  3. +2 −2 campaign/models.py
  4. +43 −0 campaign/templates/admin/campaign/subscriber/import.html
View
90 campaign/admin.py
@@ -9,13 +9,91 @@
from django.utils.translation import ugettext as _
from django.utils.encoding import force_unicode
from django.utils.safestring import mark_safe
+from django.utils import simplejson as json
from campaign.models import MailTemplate, Subscriber, Campaign, BlacklistEntry, BounceEntry
+from campaign.forms import UploadForm
-admin.site.register(MailTemplate)
-admin.site.register(Subscriber)
-admin.site.register(BlacklistEntry)
-admin.site.register(BounceEntry)
+
+class SubscriberAdmin(admin.ModelAdmin):
+
+ import_template=None
+
+ def has_import_permission(self, request):
+ """
+ TODO: integrate with django's permission system
+ """
+ return request.user.is_superuser
+
+ def import_view(self, request, extra_context=None):
+ """
+ Import email addresses and salutation from a uploaded text file.
+ """
+ model = self.model
+ opts = model._meta
+
+ if not self.has_import_permission(request):
+ raise PermissionDenied
+
+ if request.method == 'POST':
+ form = UploadForm(request.POST, request.FILES)
+ if form.is_valid():
+ data = json.loads(form.cleaned_data['file'].read())
+ num_import = 0
+ for entry in data:
+ try:
+ Subscriber.objects.create(email=entry['email'], salutation=entry['name'])
+ num_import += 1
+ except Exception, e:
+ pass
+ request.user.message_set.create(message=_(u'Successfully imported %(num_import)s %(name)s.' % {'name': force_unicode(opts.verbose_name_plural), 'num_import': num_import,}))
+ return HttpResponseRedirect('../')
+
+ else:
+ form = UploadForm()
+
+ def form_media():
+ from django.conf import settings
+ css = ['css/forms.css',]
+ return forms.Media(css={'screen': ['%s%s' % (settings.ADMIN_MEDIA_PREFIX, url) for url in css]})
+
+ media = self.media + form_media()
+ context = {
+ 'title': _('Import %s') % force_unicode(opts.verbose_name_plural),
+ 'is_popup': request.REQUEST.has_key('_popup'),
+ 'media': mark_safe(media),
+ 'root_path': self.admin_site.root_path,
+ 'app_label': opts.app_label,
+ 'opts': opts,
+ 'form': form,
+ }
+
+ context.update(extra_context or {})
+ return render_to_response(self.import_template or
+ ['admin/%s/%s/import.html' % (opts.app_label, opts.object_name.lower()),
+ 'admin/%s/import.html' % opts.app_label,
+ 'admin/import.html'], context, context_instance=template.RequestContext(request))
+
+
+ def get_urls(self):
+ from django.conf.urls.defaults import patterns, url
+
+ def wrap(view):
+ def wrapper(*args, **kwargs):
+ return self.admin_site.admin_view(view)(*args, **kwargs)
+ return update_wrapper(wrapper, view)
+
+ info = self.admin_site.name, self.model._meta.app_label, self.model._meta.module_name
+
+ super_urlpatterns = super(SubscriberAdmin, self).get_urls()
+ urlpatterns = patterns('',
+ url(r'^import/$',
+ wrap(self.import_view),
+ name='%sadmin_%s_%s_import' % info),
+ )
+ urlpatterns += super_urlpatterns
+
+ return urlpatterns
class CampaignAdmin(admin.ModelAdmin):
filter_horizontal=('recipients',)
@@ -107,3 +185,7 @@ def wrapper(*args, **kwargs):
admin.site.register(Campaign, CampaignAdmin)
+admin.site.register(MailTemplate)
+admin.site.register(Subscriber, SubscriberAdmin)
+admin.site.register(BlacklistEntry)
+admin.site.register(BounceEntry)
View
19 campaign/forms.py
@@ -0,0 +1,19 @@
+from django import forms
+from django.utils import simplejson as json
+from django.utils.translation import ugettext as _
+
+class UploadForm(forms.Form):
+ """
+ validates that the uploaded file contains parseable json data.
+ """
+ file = forms.FileField()
+
+ def clean_file(self):
+ try:
+ json.loads(self.cleaned_data['file'].read())
+ self.cleaned_data['file'].seek(0)
+ return self.cleaned_data['file']
+ except Exception, e:
+ raise forms.ValidationError(_(u"uploaded file must contain json data"))
+
+
View
4 campaign/models.py
@@ -33,7 +33,7 @@ class Recipient(models.Model):
"""
user = models.ForeignKey(User, blank=True, null=True, verbose_name=_(u"User"))
- email = models.EmailField(_(u"email address"), blank=True)
+ email = models.EmailField(_(u"email address"), blank=True, unique=True)
salutation = models.CharField(_(u"salutation"), blank=True, null=True, max_length=255)
added = models.DateTimeField(_(u"added"), editable=False)
@@ -43,7 +43,7 @@ def __unicode__(self):
def save(self, *args, **kwargs):
if not self.pk:
self.added = datetime.now()
- if self.user is not None and self.email is None:
+ if self.user is not None and not self.email:
self.email = self.user.email
return super(Recipient, self).save(*args, **kwargs)
View
43 campaign/templates/admin/campaign/subscriber/import.html
@@ -0,0 +1,43 @@
+{% extends "admin/base_site.html" %}
+{% load i18n %}
+
+{% block extrahead %}{{ block.super }}
+{{ media }}
+{% endblock %}
+
+{% block breadcrumbs %}
+<div class="breadcrumbs">
+ <a href="../../../">{% trans 'Home' %}</a> &rsaquo;
+ <a href="../../">{{ app_label|capfirst }}</a> &rsaquo;
+ <a href="../">{{ opts.verbose_name_plural|capfirst }}</a> &rsaquo;
+ {% trans 'Import' %}
+</div>
+{% endblock %}
+
+{% block content %}
+<div id="content-main">
+
+<form enctype="multipart/form-data" action="" method="post">
+<div>
+ <div class="module">
+ <div class="form-row">
+ {% blocktrans with opts.verbose_name|capfirst as model_name and object|truncatewords:"18" as object_name %}
+ Upload a file with subscribers and salutations in json format:
+ {% endblocktrans %}
+ <pre>[{"email": "info@example.com", "name": "Peter"},
+ {"email": "news@example.de", "name": "Hans"}]</pre>
+ </div>
+ <div class="form-row">
+ {{ form }}
+ </div>
+ </div>
+
+ <div class="submit-row" {% if is_popup %}style="overflow: auto;"{% endif %}>
+ <input type="submit" value="{% trans 'Import' %}" class="default" name="_submit"/>
+ <p></p>
+ </div>
+
+</div>
+</form>
+</div>
+{% endblock %}

0 comments on commit db46aae

Please sign in to comment.
Something went wrong with that request. Please try again.