|
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 the registration which was accepted " |
|
85
|
|
|
"already.")) |
|
86
|
|
|
elif action_name == 'activate': |
|
87
|
|
|
if self.instance._status != 'accepted': |
|
88
|
|
|
raise ValidationError(_( |
|
89
|
|
|
"You cannot activate the user whom registration was not " |
|
90
|
|
|
"accepted yet.")) |
|
91
|
|
|
elif action_name != 'force_activate': |
|
92
|
|
|
# with using django admin page, the code below never be called. |
|
93
|
|
|
raise ValidationError( |
|
94
|
|
|
"Unknown action_name '%s' was requested." % action_name) |
|
95
|
|
|
return self.cleaned_data['action_name'] |
|
96
|
|
|
|
|
97
|
|
|
def save(self, commit=True): |
|
98
|
|
|
"""Call appropriate action via current registration backend |
|
99
|
|
|
|
|
100
|
|
|
Insted of modifing the registration profile, this method call current |
|
101
|
|
|
registration backend's accept/reject/activate method as requested. |
|
102
|
|
|
|
|
103
|
|
|
""" |
|
104
|
|
|
fail_message = 'update' if self.instance.pk else 'create' |
|
105
|
|
|
opts = self.instance._meta |
|
106
|
|
|
if self.errors: |
|
107
|
|
|
raise ValueError("The %s chould not be %s because the data did'nt" |
|
108
|
|
|
"validate." % (opts.object_name, fail_message)) |
|
109
|
|
|
action_name = self.cleaned_data['action_name'] |
|
110
|
|
|
message = self.cleaned_data['message'] |
|
111
|
|
|
# this is a bit hack. to get request instance in form instance, |
|
112
|
|
|
# RegistrationAdmin save its request to bundle model instance |
|
113
|
|
|
_request = getattr( |
|
114
|
|
|
self.instance, |
|
115
|
|
|
settings._REGISTRATION_ADMIN_REQ_ATTR_NAME_IN_MODEL_INS |
|
116
|
|
|
) |
|
117
|
|
|
if action_name == 'accept': |
|
118
|
|
|
self.registration_backend.accept( |
|
119
|
|
|
self.instance, _request, message=message, |
|
120
|
|
|
force=True, |
|
121
|
|
|
) |
|
122
|
|
|
elif action_name == 'reject': |
|
123
|
|
|
self.registration_backend.reject( |
|
124
|
|
|
self.instance, _request, message=message) |
|
125
|
|
|
elif action_name == 'activate': |
|
126
|
|
|
# DO NOT delete profile otherwise Django Admin will raise |
|
127
|
|
|
# IndexError |
|
128
|
|
|
self.registration_backend.activate( |
|
129
|
|
|
self.instance.activation_key, _request, message=message, |
|
130
|
|
|
no_profile_delete=True, |
|
131
|
|
|
) |
|
132
|
|
|
elif action_name == 'force_activate': |
|
133
|
|
|
self.registration_backend.accept( |
|
134
|
|
|
self.instance, _request, send_email=False) |
|
135
|
|
|
# DO NOT delete profile otherwise Django Admin will raise |
|
136
|
|
|
# IndexError |
|
137
|
|
|
self.registration_backend.activate( |
|
138
|
|
|
self.instance.activation_key, _request, message=message, |
|
139
|
|
|
no_profile_delete=True, |
|
140
|
|
|
) |
|
141
|
|
|
else: |
|
142
|
|
|
raise AttributeError( |
|
143
|
|
|
'Unknwon action_name "%s" was requested.' % action_name) |
|
144
|
|
|
if action_name not in ('activate', 'force_activate'): |
|
145
|
|
|
new_instance = self.instance.__class__.objects.get( |
|
146
|
|
|
pk=self.instance.pk) |
|
147
|
|
|
else: |
|
148
|
|
|
new_instance = self.instance |
|
149
|
|
|
# the instance has been deleted by activate method however |
|
150
|
|
|
# ``save()`` method will be called, thus set mock save method |
|
151
|
|
|
new_instance.save = lambda *args, **kwargs: new_instance |
|
152
|
|
|
return new_instance |
|
153
|
|
|
|
|
154
|
|
|
# this form doesn't have ``save_m2m()`` method and it is required |
|
155
|
|
|
# in default ModelAdmin class to use. thus set mock save_m2m method |
|
156
|
|
|
save_m2m = lambda x: x |
|
157
|
|
|
|