Lock filtered objects before updating them in bulk
parent
00eb3fdb30
commit
a6fb5d0d36
|
|
@ -11,11 +11,13 @@ from django.contrib.contenttypes.admin import (GenericStackedInline,
|
||||||
GenericTabularInline)
|
GenericTabularInline)
|
||||||
from django.contrib.contenttypes.models import ContentType
|
from django.contrib.contenttypes.models import ContentType
|
||||||
from django.core.exceptions import PermissionDenied
|
from django.core.exceptions import PermissionDenied
|
||||||
from django.http import HttpResponse
|
from django.db import transaction
|
||||||
|
from django.http import HttpResponse, HttpResponseBadRequest
|
||||||
from django.shortcuts import render
|
from django.shortcuts import render
|
||||||
from django.template.defaultfilters import capfirst
|
from django.template.defaultfilters import capfirst
|
||||||
from django.utils.decorators import method_decorator
|
from django.utils.decorators import method_decorator
|
||||||
from django.utils.six.moves.urllib.parse import urlencode
|
from django.utils.six.moves.urllib.parse import urlencode
|
||||||
|
from django.utils.translation import gettext as _
|
||||||
from django.views.decorators.http import require_POST
|
from django.views.decorators.http import require_POST
|
||||||
|
|
||||||
from adminsortable.fields import SortableForeignKey
|
from adminsortable.fields import SortableForeignKey
|
||||||
|
|
@ -296,14 +298,21 @@ class SortableAdmin(SortableAdminBase, ModelAdmin):
|
||||||
response = {'objects_sorted': False}
|
response = {'objects_sorted': False}
|
||||||
|
|
||||||
if request.is_ajax():
|
if request.is_ajax():
|
||||||
try:
|
klass = ContentType.objects.get(id=model_type_id).model_class()
|
||||||
klass = ContentType.objects.get(id=model_type_id).model_class()
|
|
||||||
|
|
||||||
indexes = list(map(str,
|
indexes = [str(idx) for idx in request.POST.get('indexes', []).split(',')]
|
||||||
request.POST.get('indexes', []).split(',')))
|
|
||||||
objects_dict = dict([(str(obj.pk), obj) for obj in
|
|
||||||
klass.objects.filter(pk__in=indexes)])
|
|
||||||
|
|
||||||
|
# apply any filters via the querystring
|
||||||
|
filters = self.get_querystring_filters(request)
|
||||||
|
|
||||||
|
filters['pk__in'] = indexes
|
||||||
|
|
||||||
|
# Lock rows that we might update
|
||||||
|
qs = klass.objects.select_for_update().filter(**filters)
|
||||||
|
|
||||||
|
with transaction.atomic():
|
||||||
|
|
||||||
|
objects_dict = {str(obj.pk): obj for obj in qs}
|
||||||
order_field_name = klass._meta.ordering[0]
|
order_field_name = klass._meta.ordering[0]
|
||||||
|
|
||||||
if order_field_name.startswith('-'):
|
if order_field_name.startswith('-'):
|
||||||
|
|
@ -318,19 +327,17 @@ class SortableAdmin(SortableAdminBase, ModelAdmin):
|
||||||
|
|
||||||
start_index = getattr(start_object, order_field_name,
|
start_index = getattr(start_object, order_field_name,
|
||||||
len(indexes))
|
len(indexes))
|
||||||
|
objects_to_update = []
|
||||||
for index in indexes:
|
for index in indexes:
|
||||||
obj = objects_dict.get(index)
|
obj = objects_dict.get(index)
|
||||||
# perform the update only if the order field has changed
|
# perform the update only if the order field has changed
|
||||||
if getattr(obj, order_field_name) != start_index:
|
if getattr(obj, order_field_name) != start_index:
|
||||||
setattr(obj, order_field_name, start_index)
|
setattr(obj, order_field_name, start_index)
|
||||||
# only update the object's order field
|
objects_to_update.append(obj)
|
||||||
obj.save(update_fields=(order_field_name,))
|
|
||||||
start_index += step
|
start_index += step
|
||||||
|
|
||||||
|
qs.bulk_update(objects_to_update, [order_field_name])
|
||||||
response = {'objects_sorted': True}
|
response = {'objects_sorted': True}
|
||||||
except (KeyError, IndexError, klass.DoesNotExist,
|
|
||||||
AttributeError, ValueError):
|
|
||||||
pass
|
|
||||||
|
|
||||||
self.after_sorting()
|
self.after_sorting()
|
||||||
|
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue