1
|
|
|
# -*- coding: utf-8 -*- |
2
|
|
|
from __future__ import unicode_literals |
3
|
|
|
""" |
4
|
|
|
A forms used in RegistrationAdmin |
5
|
|
|
""" |
6
|
|
|
__author__ = 'Alisue <[email protected]>' |
7
|
|
|
__all__ = ( |
8
|
|
|
'RegistrationAdminForm', |
9
|
|
|
) |
10
|
|
|
from django import forms |
11
|
|
|
from django.core.exceptions import ValidationError |
12
|
|
|
from django.utils.translation import ugettext_lazy as _ |
13
|
|
|
|
14
|
|
|
from registration.conf import settings |
15
|
|
|
from registration.backends import get_backend |
16
|
|
|
from registration.models import RegistrationProfile |
17
|
|
|
|
18
|
|
|
|
19
|
|
|
class RegistrationAdminForm(forms.ModelForm): |
20
|
|
|
|
21
|
|
|
"""A special form for handling ``RegistrationProfile`` |
22
|
|
|
|
23
|
|
|
This form handle ``RegistrationProfile`` correctly in ``save()`` |
24
|
|
|
method. Because ``RegistrationProfile`` is not assumed to handle |
25
|
|
|
by hands, instance modification by hands is not allowed. Thus subclasses |
26
|
|
|
should feel free to add any additions they need, but should avoid |
27
|
|
|
overriding a ``save()`` method. |
28
|
|
|
|
29
|
|
|
""" |
30
|
|
|
registration_backend = get_backend() |
31
|
|
|
|
32
|
|
|
UNTREATED_ACTIONS = ( |
33
|
|
|
('accept', _('Accept this registration')), |
34
|
|
|
('reject', _('Reject this registration')), |
35
|
|
|
('force_activate', _( |
36
|
|
|
'Activate the associated user of this registration forcibly')), |
37
|
|
|
) |
38
|
|
|
ACCEPTED_ACTIONS = ( |
39
|
|
|
('accept', _('Re-accept this registration')), |
40
|
|
|
('activate', |
41
|
|
|
_('Activate the associated user of this registration')), |
42
|
|
|
) |
43
|
|
|
REJECTED_ACTIONS = ( |
44
|
|
|
('accept', _('Accept this registration')), |
45
|
|
|
('force_activate', _( |
46
|
|
|
'Activate the associated user of this registration forcibly')), |
47
|
|
|
) |
48
|
|
|
|
49
|
|
|
action_name = forms.ChoiceField(label=_('Action')) |
50
|
|
|
message = forms.CharField(label=_('Message'), |
51
|
|
|
widget=forms.Textarea, required=False, |
52
|
|
|
help_text=_( |
53
|
|
|
'You can use the value of this field in templates for acceptance, ' |
54
|
|
|
'rejection, and activation email with "{{ message }}". ' |
55
|
|
|
'It is displayed in rejection email as "Rejection reasons" in ' |
56
|
|
|
'default templates.' |
57
|
|
|
)) |
58
|
|
|
|
59
|
|
|
class Meta: |
60
|
|
|
model = RegistrationProfile |
61
|
|
|
exclude = ('user', '_status') |
62
|
|
|
|
63
|
|
|
def __init__(self, *args, **kwargs): |
64
|
|
|
super(RegistrationAdminForm, self).__init__(*args, **kwargs) |
65
|
|
|
# dynamically set choices of _status field |
66
|
|
|
if self.instance._status == 'untreated': |
67
|
|
|
self.fields['action_name'].choices = self.UNTREATED_ACTIONS |
68
|
|
|
elif self.instance._status == 'accepted': |
69
|
|
|
self.fields['action_name'].choices = self.ACCEPTED_ACTIONS |
70
|
|
|
elif self.instance._status == 'rejected': |
71
|
|
|
self.fields['action_name'].choices = self.REJECTED_ACTIONS |
72
|
|
|
|
73
|
|
|
def clean_action(self): |
74
|
|
|
"""clean action value |
75
|
|
|
|
76
|
|
|
Insted of raising AttributeError, validate the current registration |
77
|
|
|
profile status and the requested action and then raise ValidationError |
78
|
|
|
|
79
|
|
|
""" |
80
|
|
|
action_name = self.cleaned_data['action_name'] |
81
|
|
|
if action_name == 'reject': |
82
|
|
|
if self.instance._status == 'accepted': |
83
|
|
|
raise ValidationError(_( |
84
|
|
|
"You cannot reject a previously accepted registration.")) |
85
|
|
|
elif action_name == 'activate': |
86
|
|
|
if self.instance._status != 'accepted': |
87
|
|
|
raise ValidationError(_( |
88
|
|
|
"You cannot activate a user whose registration has not " |
89
|
|
|
"been accepted yet.")) |
90
|
|
|
elif action_name != 'force_activate': |
91
|
|
|
# with using django admin page, the code below never be called. |
92
|
|
|
raise ValidationError( |
93
|
|
|
"Unknown action_name '%s' was requested." % action_name) |
94
|
|
|
return self.cleaned_data['action_name'] |
95
|
|
|
|
96
|
|
|
def save(self, commit=True): |
97
|
|
|
"""Call appropriate action via current registration backend |
98
|
|
|
|
99
|
|
|
Insted of modifing the registration profile, this method call current |
100
|
|
|
registration backend's accept/reject/activate method as requested. |
101
|
|
|
|
102
|
|
|
""" |
103
|
|
|
fail_message = 'update' if self.instance.pk else 'create' |
104
|
|
|
opts = self.instance._meta |
105
|
|
|
if self.errors: |
106
|
|
|
raise ValueError("The %s chould not be %s because the data did'nt" |
107
|
|
|
"validate." % (opts.object_name, fail_message)) |
108
|
|
|
action_name = self.cleaned_data['action_name'] |
109
|
|
|
message = self.cleaned_data['message'] |
110
|
|
|
# this is a bit hack. to get request instance in form instance, |
111
|
|
|
# RegistrationAdmin save its request to bundle model instance |
112
|
|
|
_request = getattr( |
113
|
|
|
self.instance, |
114
|
|
|
settings._REGISTRATION_ADMIN_REQ_ATTR_NAME_IN_MODEL_INS |
115
|
|
|
) |
116
|
|
|
if action_name == 'accept': |
117
|
|
|
self.registration_backend.accept( |
118
|
|
|
self.instance, _request, message=message, |
119
|
|
|
force=True, |
120
|
|
|
) |
121
|
|
|
elif action_name == 'reject': |
122
|
|
|
self.registration_backend.reject( |
123
|
|
|
self.instance, _request, message=message) |
124
|
|
|
elif action_name == 'activate': |
125
|
|
|
# DO NOT delete profile otherwise Django Admin will raise |
126
|
|
|
# IndexError |
127
|
|
|
self.registration_backend.activate( |
128
|
|
|
self.instance.activation_key, _request, message=message, |
129
|
|
|
no_profile_delete=True, |
130
|
|
|
) |
131
|
|
|
elif action_name == 'force_activate': |
132
|
|
|
self.registration_backend.accept( |
133
|
|
|
self.instance, _request, send_email=False) |
134
|
|
|
# DO NOT delete profile otherwise Django Admin will raise |
135
|
|
|
# IndexError |
136
|
|
|
self.registration_backend.activate( |
137
|
|
|
self.instance.activation_key, _request, message=message, |
138
|
|
|
no_profile_delete=True, |
139
|
|
|
) |
140
|
|
|
else: |
141
|
|
|
raise AttributeError( |
142
|
|
|
'Unknwon action_name "%s" was requested.' % action_name) |
143
|
|
|
if action_name not in ('activate', 'force_activate'): |
144
|
|
|
new_instance = self.instance.__class__.objects.get( |
145
|
|
|
pk=self.instance.pk) |
146
|
|
|
else: |
147
|
|
|
new_instance = self.instance |
148
|
|
|
# the instance has been deleted by activate method however |
149
|
|
|
# ``save()`` method will be called, thus set mock save method |
150
|
|
|
new_instance.save = lambda *args, **kwargs: new_instance |
151
|
|
|
return new_instance |
152
|
|
|
|
153
|
|
|
# this form doesn't have ``save_m2m()`` method and it is required |
154
|
|
|
# in default ModelAdmin class to use. thus set mock save_m2m method |
155
|
|
|
save_m2m = lambda x: x |
156
|
|
|
|