Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Introduce backends #11

Open
wants to merge 2 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
39 changes: 37 additions & 2 deletions django_messages/__init__.py
Original file line number Diff line number Diff line change
@@ -1,2 +1,37 @@
VERSION = (0, 5, 0, 'pre')
__version__ = '.'.join(map(str, VERSION))
import pkg_resources
from django.conf import settings
from django.core.exceptions import ImproperlyConfigured
from django.utils import importlib

__version__ = pkg_resources.resource_string('django_messages', 'version.txt').strip()

def _version_tuple(__version__):
versions = __version__.split('-')
numversions = map(int, versions[0].split('.'))
return tuple(numversions + versions[1:])
VERSION = _version_tuple(__version__)

BACKEND = getattr(settings, 'MESSAGES_BACKEND',
'django_messages.backends.username.UsernameBackend')

def _get_backend(full_backend_path):
from django_messages.backends import BaseMessageBackend
module, attr = full_backend_path.rsplit('.', 1)
try:
mod = importlib.import_module(module)
except ImportError, e:
raise ImproperlyConfigured('Error importing module %s: "%s"' %
(module, e))
try:
Backend = getattr(mod, attr)
except AttributeError, e:
raise ImproperlyConfigured('Module "%s" does not define a "%s" '
'class.' % (module, attr))

if not issubclass(Backend, BaseMessageBackend):
raise ImproperlyConfigured('Backend "%s" is not a subclass of "%s"' %
(Backend, BaseMessageBackend))

return Backend()

backend = _get_backend(BACKEND)
12 changes: 12 additions & 0 deletions django_messages/backends/__init__.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@

class BaseMessageBackend(object):
"""
Abstract message backend base class.
"""
def get_name(self, user):
"""Get name from user object."""
raise NotImplementedError

def filter_users(self, names):
"""Filter users with given names."""
raise NotImplementedError
54 changes: 54 additions & 0 deletions django_messages/backends/profilename.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,54 @@
from django.conf import settings
from django.core.exceptions import ImproperlyConfigured
from django.utils import importlib
from django_messages.backends import BaseMessageBackend

class ProfilenameBackend(BaseMessageBackend):
"""
Select user with configured fieldname of AUTH_PROFILE_MODULE.
The MESSAGES_PROFILENAME_FIELDNAME setting is required.
"""
def __init__(self):
if not getattr(settings, 'AUTH_PROFILE_MODULE', False):
raise ImproperlyConfigured(
'You need to set AUTH_PROFILE_MODULE in your project settings')
try:
app, attr = settings.AUTH_PROFILE_MODULE.split('.')
module = app + '.models'
except ValueError:
raise ImproperlyConfigured(
'app_label and model_name should be separated by a dot in the '
'AUTH_PROFILE_MODULE setting')

try:
mod = importlib.import_module(module)
except ImportError, e:
raise ImproperlyConfigured('Error importing module %s: "%s"' %
(module, e))
try:
Profile = getattr(mod, attr)
except AttributeError, e:
raise ImproperlyConfigured('Module "%s" does not define a "%s" '
'class.' % (module, attr))

self.Profile = Profile

if not getattr(settings, 'MESSAGES_PROFILENAME_FIELDNAME', False):
raise ImproperlyConfigured(
'The MESSAGES_PROFILENAME_FIELDNAME setting is required for Pro'
'filename backend.')
self.fieldname = settings.MESSAGES_PROFILENAME_FIELDNAME

#if not hasattr(self.Profile, self.fieldname): # any idea?
# raise ImproperlyConfigured(
# 'Profile class "%s" does not define a "%s" field' %
# (attr, self.fieldname))

def get_name(self, user):
return getattr(user.get_profile(), self.fieldname)

def filter_users(self, names_set):
filterdict = {self.fieldname + '__in': names_set}
query = self.Profile.objects.select_related().filter(**filterdict)
users = [profile.user for profile in query]
return users
13 changes: 13 additions & 0 deletions django_messages/backends/username.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@

from django_messages.backends import BaseMessageBackend
from django.contrib.auth.models import User

class UsernameBackend(BaseMessageBackend):
"""
Select user with username of `django.contrib.auth` User.
"""
def get_name(self, user):
return user.username

def filter_users(self, names_set):
return list(User.objects.filter(username__in=names_set))
10 changes: 5 additions & 5 deletions django_messages/fields.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,8 +5,8 @@

from django import forms
from django.forms import widgets
from django.contrib.auth.models import User
from django.utils.translation import ugettext_lazy as _
from django_messages import backend


class CommaSeparatedUserInput(widgets.Input):
Expand All @@ -16,7 +16,7 @@ def render(self, name, value, attrs=None):
if value is None:
value = ''
elif isinstance(value, (list, tuple)):
value = (', '.join([user.username for user in value]))
value = (', '.join([backend.get_name(user) for user in value]))
return super(CommaSeparatedUserInput, self).render(name, value, attrs)


Expand All @@ -38,16 +38,16 @@ def clean(self, value):

names = set(value.split(','))
names_set = set([name.strip() for name in names if name.strip()])
users = list(User.objects.filter(username__in=names_set))
unknown_names = names_set ^ set([user.username for user in users])
users = backend.filter_users(names_set)
unknown_names = names_set ^ set([backend.get_name(user) for user in users])

recipient_filter = self._recipient_filter
invalid_users = []
if recipient_filter is not None:
for r in users:
if recipient_filter(r) is False:
users.remove(r)
invalid_users.append(r.username)
invalid_users.append(backend.get_name(r))

if unknown_names or invalid_users:
raise forms.ValidationError(_(u"The following usernames are incorrect: %(users)s") % {'users': ', '.join(list(unknown_names)+invalid_users)})
Expand Down
File renamed without changes.
Empty file.
1 change: 1 addition & 0 deletions django_messages/version.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
0.5.0-pre
10 changes: 6 additions & 4 deletions django_messages/views.py
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@
from django_messages.models import Message
from django_messages.forms import ComposeForm
from django_messages.utils import format_quote
from django_messages import backend

if "notification" in settings.INSTALLED_APPS:
from notification import models as notification
Expand Down Expand Up @@ -63,9 +64,9 @@ def compose(request, recipient=None, form_class=ComposeForm,
Displays and handles the ``form_class`` form to compose new messages.
Required Arguments: None
Optional Arguments:
``recipient``: username of a `django.contrib.auth` User, who should
receive the message, optionally multiple usernames
could be separated by a '+'
``recipient``: name of a user - username of `django.contrib.auth` User
at default, who should receive the message, optionally
multiple names could be separated by a '+'
``form_class``: the form-class to use
``template_name``: the template to use
``success_url``: where to redirect after successfull submission
Expand All @@ -84,7 +85,8 @@ def compose(request, recipient=None, form_class=ComposeForm,
else:
form = form_class()
if recipient is not None:
recipients = [u for u in User.objects.filter(username__in=[r.strip() for r in recipient.split('+')])]
names = [r.strip() for r in recipient.split('+')]
recipients = backend.filter_users(names)
form.fields['recipient'].initial = recipients
return render_to_response(template_name, {
'form': form,
Expand Down
8 changes: 7 additions & 1 deletion setup.py
Original file line number Diff line number Diff line change
@@ -1,8 +1,12 @@
from distutils.core import setup

def get_version():
with open('django_messages/version.txt') as f:
return f.read().strip()

setup(
name='django-messages',
version=__import__('django_messages').__version__,
version=get_version(),
description='User-to-user messaging system for Django',
long_description=open('README.rst').read(),
author='Arne Brodowski',
Expand All @@ -12,9 +16,11 @@
packages=(
'django_messages',
'django_messages.templatetags',
'django_messages.backends',
),
package_data={
'django_messages': [
'version.txt',
'templates/django_messages/*',
'templates/notification/*/*',
'locale/*/LC_MESSAGES/*',
Expand Down