forked from philippbosch/django-campaign
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
reworked how subscribers are defined. django-campaign no longer has i…
…t's own subscriber model, you now have to supply your own django model. abstracted the sending of mails with a backend-based approach. adding a MailContext which works like Django's RequestContext but based on the current Subscriber instead of the request. adding a bunch of docs. this change is definately backwards incompatible but is required for the next release.
- Loading branch information
Showing
24 changed files
with
645 additions
and
304 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,9 +1,9 @@ | ||
A basic newsletter app for the Django webframework | ||
-------------------------------------------------- | ||
|
||
See docs/overview.txt for a brief overview. | ||
* Please see the documentation in the docs folder. | ||
|
||
You can reach the author of django-campaign at arne _at_ rcs4u.de. | ||
* You can reach the author of django-campaign at arne _at_ rcs4u.de. | ||
|
||
Bug-reports can be filed at the google code project page: | ||
http://code.google.com/p/django-campaign/ | ||
* Bug-reports can be filed at the google code project page: | ||
http://code.google.com/p/django-campaign/ |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,2 +1,2 @@ | ||
VERSION = (0, 1, 1) | ||
VERSION = (0, 2, 'pre') | ||
__version__ = '.'.join(map(str, VERSION)) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,32 @@ | ||
import os | ||
from django.conf import settings | ||
from django.core.exceptions import ImproperlyConfigured | ||
|
||
__all__ = ('backend') | ||
|
||
CAMPAIGN_BACKEND = getattr(settings, 'CAMPAIGN_BACKEND', 'send_mail') | ||
|
||
def get_backend(import_path): | ||
if not '.' in import_path: | ||
import_path = "campaign.backends.%s" % import_path | ||
try: | ||
mod = __import__(import_path, {}, {}, ['']) | ||
except ImportError, e_user: | ||
# No backend found, display an error message and a list of all | ||
# bundled backends. | ||
backend_dir = __path__[0] | ||
available_backends = [f.split('.py')[0] for f in os.listdir(backend_dir) if not f.startswith('_') and not f.startswith('.') and not f.endswith('.pyc')] | ||
available_backends.sort() | ||
if CAMPAIGN_BACKEND not in available_backends: | ||
raise ImproperlyConfigured("%s isn't an available campaign backend. Available options are: %s" % \ | ||
(CAMPAIGN_BACKEND, ', '.join(map(repr, available_backends)))) | ||
# if the CAMPAIGN_BACKEND is available in the backend directory | ||
# and an ImportError is raised, don't suppress it | ||
else: | ||
raise | ||
try: | ||
return getattr(mod, 'backend') | ||
except AttributeError: | ||
raise ImproperlyConfigured('Backend "%s" does not define a "backend" instance.' % import_path) | ||
|
||
backend = get_backend(CAMPAIGN_BACKEND) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,12 @@ | ||
# an example backend which just prints out the email instead of sending it | ||
|
||
class DebugBackend(object): | ||
def send_mail(self, email, fail_silently=False): | ||
print "Subject: %s" % email.subject | ||
print "To: %s" % email.recipients() | ||
print "======" | ||
print email.message().as_string() # the actual email message | ||
print "======" | ||
return 0 | ||
|
||
backend = DebugBackend() |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,14 @@ | ||
# simple backend using django-mailer to queue and send the mails | ||
from django.conf import settings | ||
from mailer import send_mail | ||
|
||
class DjangoMailerBackend(object): | ||
def send_mail(self, email, fail_silently=False): | ||
subject = email.subject | ||
body = email.body | ||
# django_mailer does not support multi-part messages so we loose the | ||
# html content | ||
return send_mail(subject, body, settings.DEFAULT_FROM_EMAIL, email.recipients(), | ||
fail_silently=fail_silently) | ||
|
||
backend = DjangoMailerBackend() |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,15 @@ | ||
# simple backend which uses Django's built-in mail sending mechanisms | ||
|
||
class SendMailBackend(object): | ||
def send_mail(self, email, fail_silently=False): | ||
""" | ||
Parameters: | ||
``email``: an instance of django.core.mail.EmailMessage | ||
``fail_silently``: a boolean indicating if exceptions should | ||
bubble up | ||
""" | ||
return email.send(fail_silently=fail_silently) | ||
|
||
backend = SendMailBackend() |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,44 @@ | ||
# heavily based on Django's RequestContext | ||
from django.conf import settings | ||
from django.core.exceptions import ImproperlyConfigured | ||
from django.template import Context | ||
|
||
_mail_context_processors = None | ||
|
||
# This is a function rather than module-level procedural code because we only | ||
# want it to execute if somebody uses MailContext. | ||
def get_mail_processors(): | ||
global _mail_context_processors | ||
if _mail_context_processors is None: | ||
processors = [] | ||
for path in getattr(settings, 'CAMPAIGN_CONTEXT_PROCESSORS', ()): | ||
i = path.rfind('.') | ||
module, attr = path[:i], path[i+1:] | ||
try: | ||
mod = __import__(module, {}, {}, [attr]) | ||
except ImportError, e: | ||
raise ImproperlyConfigured('Error importing campaign processor module %s: "%s"' % (module, e)) | ||
try: | ||
func = getattr(mod, attr) | ||
except AttributeError: | ||
raise ImproperlyConfigured('Module "%s" does not define a "%s" callable campaign processor' % (module, attr)) | ||
processors.append(func) | ||
_mail_context_processors = tuple(processors) | ||
return _mail_context_processors | ||
|
||
class MailContext(Context): | ||
""" | ||
This subclass of template.Context automatically populates itself using | ||
the processors defined in CAMPAIGN_CONTEXT_PROCESSORS. | ||
Additional processors can be specified as a list of callables | ||
using the "processors" keyword argument. | ||
""" | ||
def __init__(self, subscriber, dict=None, processors=None): | ||
Context.__init__(self, dict) | ||
if processors is None: | ||
processors = () | ||
else: | ||
processors = tuple(processors) | ||
for processor in get_mail_processors() + processors: | ||
self.update(processor(subscriber)) | ||
self.update({'recipient': subscriber}) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,41 @@ | ||
from django.db import models | ||
from django import forms | ||
from django.utils import simplejson | ||
|
||
class JSONWidget(forms.Textarea): | ||
def render(self, name, value, attrs=None): | ||
if not isinstance(value, basestring): | ||
value = simplejson.dumps(value, indent=2) | ||
return super(JSONWidget, self).render(name, value, attrs) | ||
|
||
class JSONFormField(forms.CharField): | ||
def __init__(self, *args, **kwargs): | ||
kwargs['widget'] = JSONWidget | ||
super(JSONFormField, self).__init__(*args, **kwargs) | ||
|
||
def clean(self, value): | ||
if not value: return | ||
try: | ||
return simplejson.loads(value) | ||
except Exception, exc: | ||
raise forms.ValidationError(u'JSON decode error: %s' % (unicode(exc),)) | ||
|
||
class JSONField(models.TextField): | ||
__metaclass__ = models.SubfieldBase | ||
|
||
def formfield(self, **kwargs): | ||
return super(JSONField, self).formfield(form_class=JSONFormField, **kwargs) | ||
|
||
def to_python(self, value): | ||
if isinstance(value, basestring): | ||
value = simplejson.loads(value) | ||
return value | ||
|
||
def get_db_prep_save(self, value): | ||
if value is None: return | ||
return simplejson.dumps(value) | ||
|
||
def value_to_string(self, obj): | ||
value = self._get_val_from_obj(obj) | ||
return self.get_db_prep_value(value) | ||
|
This file was deleted.
Oops, something went wrong.
Oops, something went wrong.