10
10
from django .db import transaction
11
11
from django .db .models import Q
12
12
from django .forms import CheckboxInput
13
- from django .forms .formsets import INITIAL_FORM_COUNT , ManagementForm , MAX_NUM_FORM_COUNT , TOTAL_FORM_COUNT
13
+ from django .forms .formsets import (
14
+ INITIAL_FORM_COUNT ,
15
+ ManagementForm ,
16
+ MAX_NUM_FORM_COUNT ,
17
+ TOTAL_FORM_COUNT ,
18
+ )
14
19
from django .forms .models import BaseModelFormSet
15
20
from django .http import HttpResponse , HttpResponseRedirect
16
21
from django .utils .encoding import force_str
@@ -39,7 +44,9 @@ def action_checkbox(self, obj):
39
44
if self .check_concurrent_action :
40
45
attrs = {
41
46
"class" : "action-select" ,
42
- "aria-label" : format_html (_ ("Select this object for an action - {}" ), obj ),
47
+ "aria-label" : format_html (
48
+ _ ("Select this object for an action - {}" ), obj
49
+ ),
43
50
}
44
51
checkbox = CheckboxInput (attrs , lambda value : False )
45
52
pk = force_str ("%s,%s" % (obj .pk , get_revision_of_object (obj )))
@@ -50,7 +57,9 @@ def action_checkbox(self, obj):
50
57
else : # pragma: no cover
51
58
return super ().action_checkbox (obj )
52
59
53
- action_checkbox .short_description = mark_safe ('<input type="checkbox" id="action-toggle" />' )
60
+ action_checkbox .short_description = mark_safe (
61
+ '<input type="checkbox" id="action-toggle" />'
62
+ )
54
63
action_checkbox .allow_tags = True
55
64
56
65
def get_confirmation_template (self ):
@@ -66,7 +75,7 @@ def response_action(self, request, queryset): # noqa
66
75
# and bottom of the change list, for example). Get the action
67
76
# whose button was pushed.
68
77
try :
69
- action_index = int (request .POST .get (' index' , 0 ))
78
+ action_index = int (request .POST .get (" index" , 0 ))
70
79
except ValueError : # pragma: no cover
71
80
action_index = 0
72
81
@@ -77,24 +86,24 @@ def response_action(self, request, queryset): # noqa
77
86
78
87
# Use the action whose button was pushed
79
88
try :
80
- data .update ({' action' : data .getlist (' action' )[action_index ]})
89
+ data .update ({" action" : data .getlist (" action" )[action_index ]})
81
90
except IndexError : # pragma: no cover
82
91
# If we didn't get an action from the chosen form that's invalid
83
92
# POST data, so by deleting action it'll fail the validation check
84
93
# below. So no need to do anything here
85
94
pass
86
95
87
96
action_form = self .action_form (data , auto_id = None )
88
- action_form .fields [' action' ].choices = self .get_action_choices (request )
97
+ action_form .fields [" action" ].choices = self .get_action_choices (request )
89
98
90
99
# If the form's valid we can handle the action.
91
100
if action_form .is_valid ():
92
- action = action_form .cleaned_data [' action' ]
101
+ action = action_form .cleaned_data [" action" ]
93
102
func , name , description = self .get_actions (request )[action ]
94
103
95
104
# Get the list of selected PKs. If nothing's selected, we can't
96
105
# perform an action on it, so bail.
97
- if action_form .cleaned_data [' select_across' ]:
106
+ if action_form .cleaned_data [" select_across" ]:
98
107
selected = ALL
99
108
else :
100
109
selected = request .POST .getlist (helpers .ACTION_CHECKBOX_NAME )
@@ -105,7 +114,9 @@ def response_action(self, request, queryset): # noqa
105
114
revision_field = self .model ._concurrencymeta .field
106
115
107
116
if self .check_concurrent_action :
108
- self .delete_selected_confirmation_template = self .get_confirmation_template ()
117
+ self .delete_selected_confirmation_template = (
118
+ self .get_confirmation_template ()
119
+ )
109
120
110
121
# If select_across we have to avoid the use of concurrency
111
122
if selected is not ALL :
@@ -114,20 +125,27 @@ def response_action(self, request, queryset): # noqa
114
125
try :
115
126
pk , version = x .split ("," )
116
127
except ValueError : # pragma: no cover
117
- raise ImproperlyConfigured ('`ConcurrencyActionMixin` error.'
118
- 'A tuple with `primary_key, version_number` '
119
- 'expected: `%s` found' % x )
120
- filters .append (Q (** {'pk' : pk ,
121
- revision_field .attname : version }))
128
+ raise ImproperlyConfigured (
129
+ "`ConcurrencyActionMixin` error."
130
+ "A tuple with `primary_key, version_number` "
131
+ "expected: `%s` found" % x
132
+ )
133
+ filters .append (Q (** {"pk" : pk , revision_field .attname : version }))
122
134
123
135
queryset = queryset .filter (reduce (operator .or_ , filters ))
124
136
if len (selected ) != queryset .count ():
125
- messages .error (request , 'One or more record were updated. '
126
- '(Probably by other user) '
127
- 'The execution was aborted.' )
137
+ messages .error (
138
+ request ,
139
+ "One or more record were updated. "
140
+ "(Probably by other user) "
141
+ "The execution was aborted." ,
142
+ )
128
143
return HttpResponseRedirect ("." )
129
144
else :
130
- messages .warning (request , 'Selecting all records, you will avoid the concurrency check' )
145
+ messages .warning (
146
+ request ,
147
+ "Selecting all records, you will avoid the concurrency check" ,
148
+ )
131
149
132
150
response = func (self , request , queryset )
133
151
@@ -142,13 +160,15 @@ def response_action(self, request, queryset): # noqa
142
160
143
161
class ConcurrentManagementForm (ManagementForm ):
144
162
def __init__ (self , * args , ** kwargs ):
145
- self ._versions = kwargs .pop (' versions' , [])
163
+ self ._versions = kwargs .pop (" versions" , [])
146
164
super ().__init__ (* args , ** kwargs )
147
165
148
166
def _get_concurrency_fields (self ):
149
167
v = []
150
168
for pk , version in self ._versions :
151
- v .append (f'<input type="hidden" name="{ concurrency_param_name } _{ pk } " value="{ version } ">' )
169
+ v .append (
170
+ f'<input type="hidden" name="{ concurrency_param_name } _{ pk } " value="{ version } ">'
171
+ )
152
172
return mark_safe ("" .join (v ))
153
173
154
174
def render (self , template_name = None , context = None , renderer = None ):
@@ -163,27 +183,40 @@ def __str__(self):
163
183
164
184
__html__ = __str__
165
185
166
- def _html_output (self , normal_row , error_row , row_ender , help_text_html , errors_on_separate_row ):
167
- ret = super ()._html_output (normal_row , error_row , row_ender , help_text_html , errors_on_separate_row )
186
+ def _html_output (
187
+ self , normal_row , error_row , row_ender , help_text_html , errors_on_separate_row
188
+ ):
189
+ ret = super ()._html_output (
190
+ normal_row , error_row , row_ender , help_text_html , errors_on_separate_row
191
+ )
168
192
return mark_safe ("{0}{1}" .format (ret , self ._get_concurrency_fields ()))
169
193
170
194
171
195
class ConcurrentBaseModelFormSet (BaseModelFormSet ):
172
196
def _management_form (self ):
173
197
"""Returns the ManagementForm instance for this FormSet."""
174
198
if self .is_bound :
175
- form = ConcurrentManagementForm (self .data , auto_id = self .auto_id ,
176
- prefix = self .prefix )
199
+ form = ConcurrentManagementForm (
200
+ self .data , auto_id = self .auto_id , prefix = self .prefix
201
+ )
177
202
if not form .is_valid ():
178
- raise ValidationError ('ManagementForm data is missing or has been tampered with' )
203
+ raise ValidationError (
204
+ "ManagementForm data is missing or has been tampered with"
205
+ )
179
206
else :
180
- form = ConcurrentManagementForm (auto_id = self .auto_id ,
181
- prefix = self .prefix ,
182
- initial = {TOTAL_FORM_COUNT : self .total_form_count (),
183
- INITIAL_FORM_COUNT : self .initial_form_count (),
184
- MAX_NUM_FORM_COUNT : self .max_num },
185
- versions = [(form .instance .pk , get_revision_of_object (form .instance )) for form
186
- in self .initial_forms ])
207
+ form = ConcurrentManagementForm (
208
+ auto_id = self .auto_id ,
209
+ prefix = self .prefix ,
210
+ initial = {
211
+ TOTAL_FORM_COUNT : self .total_form_count (),
212
+ INITIAL_FORM_COUNT : self .initial_form_count (),
213
+ MAX_NUM_FORM_COUNT : self .max_num ,
214
+ },
215
+ versions = [
216
+ (form .instance .pk , get_revision_of_object (form .instance ))
217
+ for form in self .initial_forms
218
+ ],
219
+ )
187
220
return form
188
221
189
222
management_form = property (_management_form )
@@ -193,17 +226,17 @@ class ConcurrencyListEditableMixin:
193
226
list_editable_policy = conf .POLICY
194
227
195
228
def get_changelist_formset (self , request , ** kwargs ):
196
- kwargs [' formset' ] = ConcurrentBaseModelFormSet
229
+ kwargs [" formset" ] = ConcurrentBaseModelFormSet
197
230
return super ().get_changelist_formset (request , ** kwargs )
198
231
199
232
def _add_conflict (self , request , obj ):
200
- if hasattr (request , ' _concurrency_list_editable_errors' ):
233
+ if hasattr (request , " _concurrency_list_editable_errors" ):
201
234
request ._concurrency_list_editable_errors .append (obj .pk )
202
235
else :
203
236
request ._concurrency_list_editable_errors = [obj .pk ]
204
237
205
238
def _get_conflicts (self , request ):
206
- if hasattr (request , ' _concurrency_list_editable_errors' ):
239
+ if hasattr (request , " _concurrency_list_editable_errors" ):
207
240
return request ._concurrency_list_editable_errors
208
241
else :
209
242
return []
@@ -212,7 +245,7 @@ def _get_conflicts(self, request):
212
245
def save_model (self , request , obj , form , change ):
213
246
try :
214
247
if change :
215
- version = request .POST .get (f' { concurrency_param_name } _{ obj .pk } ' , None )
248
+ version = request .POST .get (f" { concurrency_param_name } _{ obj .pk } " , None )
216
249
if version :
217
250
core ._set_version (obj , version )
218
251
super ().save_model (request , obj , form , change )
@@ -248,33 +281,38 @@ def message_user(self, request, message, *args, **kwargs):
248
281
m = rex .match (message )
249
282
concurrency_errros = len (conflicts )
250
283
if m :
251
- updated_record = int (m .group (' num' )) - concurrency_errros
284
+ updated_record = int (m .group (" num" )) - concurrency_errros
252
285
253
286
ids = "," .join (map (str , conflicts ))
254
- messages .error (request ,
255
- ngettext ("Record with pk `{0}` has been modified and was not updated" ,
256
- "Records `{0}` have been modified and were not updated" ,
257
- concurrency_errros ).format (ids ))
287
+ messages .error (
288
+ request ,
289
+ ngettext (
290
+ "Record with pk `{0}` has been modified and was not updated" ,
291
+ "Records `{0}` have been modified and were not updated" ,
292
+ concurrency_errros ,
293
+ ).format (ids ),
294
+ )
258
295
if updated_record == 1 :
259
296
name = force_str (opts .verbose_name )
260
297
else :
261
298
name = force_str (opts .verbose_name_plural )
262
299
263
300
message = None
264
301
if updated_record > 0 :
265
- message = ngettext ("%(count)s %(name)s was changed successfully." ,
266
- "%(count)s %(name)s were changed successfully." ,
267
- updated_record ) % {'count' : updated_record ,
268
- 'name' : name }
302
+ message = ngettext (
303
+ "%(count)s %(name)s was changed successfully." ,
304
+ "%(count)s %(name)s were changed successfully." ,
305
+ updated_record ,
306
+ ) % {"count" : updated_record , "name" : name }
269
307
270
308
return super ().message_user (request , message , * args , ** kwargs )
271
309
272
310
273
- class ConcurrentModelAdmin (ConcurrencyActionMixin ,
274
- ConcurrencyListEditableMixin ,
275
- admin . ModelAdmin ):
311
+ class ConcurrentModelAdmin (
312
+ ConcurrencyActionMixin , ConcurrencyListEditableMixin , admin . ModelAdmin
313
+ ):
276
314
form = ConcurrentForm
277
- formfield_overrides = {forms .VersionField : {' widget' : VersionWidget }}
315
+ formfield_overrides = {forms .VersionField : {" widget" : VersionWidget }}
278
316
279
317
def check (self , ** kwargs ):
280
318
errors = super ().check (** kwargs )
@@ -283,23 +321,27 @@ def check(self, **kwargs):
283
321
if version_field .name not in self .fields :
284
322
errors .append (
285
323
Error (
286
- 'Missed version field in {} fields definition' .format (self ),
287
- hint = "Please add '{}' to the 'fields' attribute" .format (version_field .name ),
324
+ "Missed version field in {} fields definition" .format (self ),
325
+ hint = "Please add '{}' to the 'fields' attribute" .format (
326
+ version_field .name
327
+ ),
288
328
obj = None ,
289
- id = ' concurrency.A001' ,
329
+ id = " concurrency.A001" ,
290
330
)
291
331
)
292
332
if self .fieldsets :
293
333
version_field = self .model ._concurrencymeta .field
294
- fields = flatten ([v [' fields' ] for k , v in self .fieldsets ])
334
+ fields = flatten ([v [" fields" ] for k , v in self .fieldsets ])
295
335
296
336
if version_field .name not in fields :
297
337
errors .append (
298
338
Error (
299
- 'Missed version field in {} fieldsets definition' .format (self ),
300
- hint = "Please add '{}' to the 'fieldsets' attribute" .format (version_field .name ),
339
+ "Missed version field in {} fieldsets definition" .format (self ),
340
+ hint = "Please add '{}' to the 'fieldsets' attribute" .format (
341
+ version_field .name
342
+ ),
301
343
obj = None ,
302
- id = ' concurrency.A002' ,
344
+ id = " concurrency.A002" ,
303
345
)
304
346
)
305
347
return errors
0 commit comments