Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 2 additions & 2 deletions netbox/circuits/views.py
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
from django.contrib import messages
from django.db import transaction
from django.db import router, transaction
from django.shortcuts import get_object_or_404, redirect, render
from django.utils.translation import gettext_lazy as _

Expand Down Expand Up @@ -384,7 +384,7 @@ def post(self, request, pk):

if termination_a and termination_z:
# Use a placeholder to avoid an IntegrityError on the (circuit, term_side) unique constraint
with transaction.atomic():
with transaction.atomic(using=router.db_for_write(CircuitTermination)):
termination_a.term_side = '_'
termination_a.save()
termination_z.term_side = 'A'
Expand Down
4 changes: 2 additions & 2 deletions netbox/dcim/utils.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
from django.apps import apps
from django.contrib.contenttypes.models import ContentType
from django.db import transaction
from django.db import router, transaction


def compile_path_node(ct_id, object_id):
Expand Down Expand Up @@ -53,7 +53,7 @@ def rebuild_paths(terminations):
for obj in terminations:
cable_paths = CablePath.objects.filter(_nodes__contains=obj)

with transaction.atomic():
with transaction.atomic(using=router.db_for_write(CablePath)):
for cp in cable_paths:
cp.delete()
create_cablepath(cp.origins)
Expand Down
6 changes: 3 additions & 3 deletions netbox/dcim/views.py
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
from django.contrib import messages
from django.contrib.contenttypes.models import ContentType
from django.core.paginator import EmptyPage, PageNotAnInteger
from django.db import transaction
from django.db import router, transaction
from django.db.models import Prefetch
from django.forms import ModelMultipleChoiceField, MultipleHiddenInput, modelformset_factory
from django.shortcuts import get_object_or_404, redirect, render
Expand Down Expand Up @@ -124,7 +124,7 @@ def post(self, request):

if form.is_valid():

with transaction.atomic():
with transaction.atomic(using=router.db_for_write(Cable)):
count = 0
cable_ids = set()
for obj in self.queryset.filter(pk__in=form.cleaned_data['pk']):
Expand Down Expand Up @@ -3746,7 +3746,7 @@ def post(self, request, pk):

if vc_form.is_valid() and formset.is_valid():

with transaction.atomic():
with transaction.atomic(using=router.db_for_write(Device)):

# Save the VirtualChassis
vc_form.save()
Expand Down
3 changes: 3 additions & 0 deletions netbox/extras/jobs.py
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,9 @@ def run_script(self, script, request, data, commit):

try:
try:
# A script can modify multiple models so need to do an atomic lock on
# both the default database (for non ChangeLogged models) and potentially
# any other database (for ChangeLogged models)
with transaction.atomic():
script.output = script.run(data, commit)
if not commit:
Expand Down
4 changes: 2 additions & 2 deletions netbox/ipam/api/views.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@

from django.contrib.contenttypes.prefetch import GenericPrefetch
from django.core.exceptions import ObjectDoesNotExist, PermissionDenied
from django.db import transaction
from django.db import router, transaction
from django.shortcuts import get_object_or_404
from django.utils.translation import gettext as _
from django_pglocks import advisory_lock
Expand Down Expand Up @@ -295,7 +295,7 @@ def post(self, request, pk):

# Create the new IP address(es)
try:
with transaction.atomic():
with transaction.atomic(using=router.db_for_write(self.queryset.model)):
created = serializer.save()
self._validate_objects(created)
except ObjectDoesNotExist:
Expand Down
6 changes: 3 additions & 3 deletions netbox/netbox/api/viewsets/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
from functools import cached_property

from django.core.exceptions import ObjectDoesNotExist, PermissionDenied
from django.db import transaction
from django.db import router, transaction
from django.db.models import ProtectedError, RestrictedError
from django_pglocks import advisory_lock
from netbox.constants import ADVISORY_LOCK_KEYS
Expand Down Expand Up @@ -170,7 +170,7 @@ def perform_create(self, serializer):

# Enforce object-level permissions on save()
try:
with transaction.atomic():
with transaction.atomic(using=router.db_for_write(model)):
instance = serializer.save()
self._validate_objects(instance)
except ObjectDoesNotExist:
Expand All @@ -190,7 +190,7 @@ def perform_update(self, serializer):

# Enforce object-level permissions on save()
try:
with transaction.atomic():
with transaction.atomic(using=router.db_for_write(model)):
instance = serializer.save()
self._validate_objects(instance)
except ObjectDoesNotExist:
Expand Down
32 changes: 16 additions & 16 deletions netbox/netbox/api/viewsets/mixins.py
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
from django.core.exceptions import ObjectDoesNotExist
from django.db import transaction
from django.db import router, transaction
from django.http import Http404
from rest_framework import status
from rest_framework.response import Response
Expand Down Expand Up @@ -56,22 +56,22 @@ class SequentialBulkCreatesMixin:
which depends on the evaluation of existing objects (such as checking for free space within a rack) functions
appropriately.
"""
@transaction.atomic
def create(self, request, *args, **kwargs):
if not isinstance(request.data, list):
# Creating a single object
return super().create(request, *args, **kwargs)

return_data = []
for data in request.data:
serializer = self.get_serializer(data=data)
serializer.is_valid(raise_exception=True)
self.perform_create(serializer)
return_data.append(serializer.data)
with transaction.atomic(using=router.db_for_write(self.queryset.model)):
if not isinstance(request.data, list):
# Creating a single object
return super().create(request, *args, **kwargs)

return_data = []
for data in request.data:
serializer = self.get_serializer(data=data)
serializer.is_valid(raise_exception=True)
self.perform_create(serializer)
return_data.append(serializer.data)

headers = self.get_success_headers(serializer.data)
headers = self.get_success_headers(serializer.data)

return Response(return_data, status=status.HTTP_201_CREATED, headers=headers)
return Response(return_data, status=status.HTTP_201_CREATED, headers=headers)


class BulkUpdateModelMixin:
Expand Down Expand Up @@ -113,7 +113,7 @@ def bulk_update(self, request, *args, **kwargs):
return Response(data, status=status.HTTP_200_OK)

def perform_bulk_update(self, objects, update_data, partial):
with transaction.atomic():
with transaction.atomic(using=router.db_for_write(self.queryset.model)):
data_list = []
for obj in objects:
data = update_data.get(obj.id)
Expand Down Expand Up @@ -157,7 +157,7 @@ def bulk_destroy(self, request, *args, **kwargs):
return Response(status=status.HTTP_204_NO_CONTENT)

def perform_bulk_destroy(self, objects):
with transaction.atomic():
with transaction.atomic(using=router.db_for_write(self.queryset.model)):
for obj in objects:
if hasattr(obj, 'snapshot'):
obj.snapshot()
Expand Down
14 changes: 7 additions & 7 deletions netbox/netbox/views/generic/bulk_views.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@
from django.contrib.contenttypes.fields import GenericForeignKey, GenericRel
from django.contrib.contenttypes.models import ContentType
from django.core.exceptions import FieldDoesNotExist, ObjectDoesNotExist, ValidationError
from django.db import transaction, IntegrityError
from django.db import IntegrityError, router, transaction
from django.db.models import ManyToManyField, ProtectedError, RestrictedError
from django.db.models.fields.reverse_related import ManyToManyRel
from django.forms import ModelMultipleChoiceField, MultipleHiddenInput
Expand Down Expand Up @@ -278,7 +278,7 @@ def post(self, request):
logger.debug("Form validation was successful")

try:
with transaction.atomic():
with transaction.atomic(using=router.db_for_write(model)):
new_objs = self._create_objects(form, request)

# Enforce object-level permissions
Expand Down Expand Up @@ -501,7 +501,7 @@ def post(self, request):

try:
# Iterate through data and bind each record to a new model form instance.
with transaction.atomic():
with transaction.atomic(using=router.db_for_write(model)):
new_objs = self.create_and_update_objects(form, request)

# Enforce object-level permissions
Expand Down Expand Up @@ -681,7 +681,7 @@ def post(self, request, **kwargs):
if form.is_valid():
logger.debug("Form validation was successful")
try:
with transaction.atomic():
with transaction.atomic(using=router.db_for_write(model)):
updated_objects = self._update_objects(form, request)

# Enforce object-level permissions
Expand Down Expand Up @@ -778,7 +778,7 @@ def post(self, request):

if form.is_valid():
try:
with transaction.atomic():
with transaction.atomic(using=router.db_for_write(self.queryset.model)):
renamed_pks = self._rename_objects(form, selected_objects)

if '_apply' in request.POST:
Expand Down Expand Up @@ -875,7 +875,7 @@ def post(self, request, **kwargs):
queryset = self.queryset.filter(pk__in=pk_list)
deleted_count = queryset.count()
try:
with transaction.atomic():
with transaction.atomic(using=router.db_for_write(model)):
for obj in queryset:
# Take a snapshot of change-logged models
if hasattr(obj, 'snapshot'):
Expand Down Expand Up @@ -980,7 +980,7 @@ def post(self, request):
}

try:
with transaction.atomic():
with transaction.atomic(using=router.db_for_write(self.queryset.model)):

for obj in data['pk']:

Expand Down
4 changes: 2 additions & 2 deletions netbox/netbox/views/generic/feature_views.py
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
from django.contrib.auth.mixins import LoginRequiredMixin
from django.contrib.contenttypes.models import ContentType
from django.contrib import messages
from django.db import transaction
from django.db import router, transaction
from django.db.models import Q
from django.shortcuts import get_object_or_404, redirect, render
from django.utils.translation import gettext_lazy as _
Expand Down Expand Up @@ -240,7 +240,7 @@ def post(self, request):
data_file__isnull=False
)

with transaction.atomic():
with transaction.atomic(using=router.db_for_write(self.queryset.model)):
for obj in selected_objects:
obj.sync(save=True)

Expand Down
4 changes: 2 additions & 2 deletions netbox/netbox/views/generic/object_views.py
Original file line number Diff line number Diff line change
Expand Up @@ -282,7 +282,7 @@ def post(self, request, *args, **kwargs):
logger.debug("Form validation was successful")

try:
with transaction.atomic():
with transaction.atomic(using=router.db_for_write(model)):
object_created = form.instance.pk is None
obj = form.save()

Expand Down Expand Up @@ -570,7 +570,7 @@ def post(self, request):

if not form.errors and not component_form.errors:
try:
with transaction.atomic():
with transaction.atomic(using=router.db_for_write(self.queryset.model)):
# Create the new components
new_objs = []
for component_form in new_components:
Expand Down
6 changes: 3 additions & 3 deletions netbox/virtualization/views.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
from django.contrib import messages
from django.contrib.contenttypes.models import ContentType
from django.db import transaction
from django.db import router, transaction
from django.db.models import Prefetch, Sum
from django.shortcuts import get_object_or_404, redirect, render
from django.urls import reverse
Expand Down Expand Up @@ -297,7 +297,7 @@ def post(self, request, pk):
if form.is_valid():

device_pks = form.cleaned_data['devices']
with transaction.atomic():
with transaction.atomic(using=router.db_for_write(Device)):

# Assign the selected Devices to the Cluster
for device in Device.objects.filter(pk__in=device_pks):
Expand Down Expand Up @@ -332,7 +332,7 @@ def post(self, request, pk):
if form.is_valid():

device_pks = form.cleaned_data['pk']
with transaction.atomic():
with transaction.atomic(using=router.db_for_write(Device)):

# Remove the selected Devices from the Cluster
for device in Device.objects.filter(pk__in=device_pks):
Expand Down