Source code for registration.admin.forms
# -*- coding: utf-8 -*-
from __future__ import unicode_literals
"""
A forms used in RegistrationAdmin
"""
__author__ = 'Alisue <lambdalisue@hashnote.net>'
__all__ = (
'RegistrationAdminForm',
)
from django import forms
from django.core.exceptions import ValidationError
from django.utils.translation import ugettext_lazy as _
from registration.conf import settings
from registration.backends import get_backend
from registration.models import RegistrationProfile
[docs]class RegistrationAdminForm(forms.ModelForm):
"""A special form for handling ``RegistrationProfile``
This form handle ``RegistrationProfile`` correctly in ``save()``
method. Because ``RegistrationProfile`` is not assumed to handle
by hands, instance modification by hands is not allowed. Thus subclasses
should feel free to add any additions they need, but should avoid
overriding a ``save()`` method.
"""
registration_backend = get_backend()
UNTREATED_ACTIONS = (
('accept', _('Accept this registration')),
('reject', _('Reject this registration')),
('force_activate', _(
'Activate the associated user of this registration forcibly')),
)
ACCEPTED_ACTIONS = (
('accept', _('Re-accept this registration')),
('activate',
_('Activate the associated user of this registration')),
)
REJECTED_ACTIONS = (
('accept', _('Accept this registration')),
('force_activate', _(
'Activate the associated user of this registration forcibly')),
)
action_name = forms.ChoiceField(label=_('Action'))
message = forms.CharField(label=_('Message'),
widget=forms.Textarea, required=False,
help_text=_(
'You can use the value of this field in templates for acceptance, '
'rejection, and activation email with "{{ message }}". '
'It is displayed in rejection email as "Rejection reasons" in '
'default templates.'
))
def __init__(self, *args, **kwargs):
super(RegistrationAdminForm, self).__init__(*args, **kwargs)
# dynamically set choices of _status field
if self.instance._status == 'untreated':
self.fields['action_name'].choices = self.UNTREATED_ACTIONS
elif self.instance._status == 'accepted':
self.fields['action_name'].choices = self.ACCEPTED_ACTIONS
elif self.instance._status == 'rejected':
self.fields['action_name'].choices = self.REJECTED_ACTIONS
[docs] def clean_action(self):
"""clean action value
Insted of raising AttributeError, validate the current registration
profile status and the requested action and then raise ValidationError
"""
action_name = self.cleaned_data['action_name']
if action_name == 'reject':
if self.instance._status == 'accepted':
raise ValidationError(_(
"You cannot reject a previously accepted registration."))
elif action_name == 'activate':
if self.instance._status != 'accepted':
raise ValidationError(_(
"You cannot activate a user whose registration has not "
"been accepted yet."))
elif action_name != 'force_activate':
# with using django admin page, the code below never be called.
raise ValidationError(
"Unknown action_name '%s' was requested." % action_name)
return self.cleaned_data['action_name']
[docs] def save(self, commit=True):
"""Call appropriate action via current registration backend
Insted of modifing the registration profile, this method call current
registration backend's accept/reject/activate method as requested.
"""
fail_message = 'update' if self.instance.pk else 'create'
opts = self.instance._meta
if self.errors:
raise ValueError("The %s chould not be %s because the data did'nt"
"validate." % (opts.object_name, fail_message))
action_name = self.cleaned_data['action_name']
message = self.cleaned_data['message']
# this is a bit hack. to get request instance in form instance,
# RegistrationAdmin save its request to bundle model instance
_request = getattr(
self.instance,
settings._REGISTRATION_ADMIN_REQ_ATTR_NAME_IN_MODEL_INS
)
if action_name == 'accept':
self.registration_backend.accept(
self.instance, _request, message=message,
force=True,
)
elif action_name == 'reject':
self.registration_backend.reject(
self.instance, _request, message=message)
elif action_name == 'activate':
# DO NOT delete profile otherwise Django Admin will raise
# IndexError
self.registration_backend.activate(
self.instance.activation_key, _request, message=message,
no_profile_delete=True,
)
elif action_name == 'force_activate':
self.registration_backend.accept(
self.instance, _request, send_email=False)
# DO NOT delete profile otherwise Django Admin will raise
# IndexError
self.registration_backend.activate(
self.instance.activation_key, _request, message=message,
no_profile_delete=True,
)
else:
raise AttributeError(
'Unknwon action_name "%s" was requested.' % action_name)
if action_name not in ('activate', 'force_activate'):
new_instance = self.instance.__class__.objects.get(
pk=self.instance.pk)
else:
new_instance = self.instance
# the instance has been deleted by activate method however
# ``save()`` method will be called, thus set mock save method
new_instance.save = lambda *args, **kwargs: new_instance
return new_instance
# this form doesn't have ``save_m2m()`` method and it is required
# in default ModelAdmin class to use. thus set mock save_m2m method
save_m2m = lambda x: x