Reputation: 572
I have a Django Rest API to return a value.
This API may be hit at the same time/
Is django rest api thread safe?
$http.get('//0.0.0.0:8000/api/tempName?format=json')
.success(function (data) {
$scope.iterativeNum = data.iterativeField
})
In the views.py
class ApiDetail(generics.RetrieveUpdateDestroyAPIView):
queryset = Api.objects.all()
serializer_class = ApiSerializer
def get(self, request, *args, **kwargs):
currentForm = self.kwargs['pk']
currentApi = Api.objects.get(pk = currentItem)
currentApi.currentNumber += 1
tempCurrentNum = currentApi.currentNumber
strCurrentNum = str(tempCurrentNum)
currentNumLength = len(strCurrentNum)
if(currentNumLength > currentApi.maxNumberOfDigitsInNum):
currentApi.currentNumber = 1
currentApi.iterativeField = currentApi.fieldPrefix + str(currentApi.currentNumber)
currentApi.save()
return self.retrieve(request, *args, **kwargs)
I am concerned two seperate calls can hit the 'ApiDetail' view and return the same number before.
I'm working on a Mac using Python/Django. Django 1.9.4, Django Rest 3.3.3.
Upvotes: 2
Views: 2348
Reputation: 12558
You could wrap everything into a transaction with transaction.atomic()
def get(self, request, *args, **kwargs):
with transaction.atomic()
currentApi = Api.objects.get(pk=currentItem)
...
currentApi.save()
return self.retrieve(request, *args, **kwargs)
Upvotes: 1
Reputation: 5819
I believe the problem here will be more your code, than django-rest-framework. What you want to use is an F()
expression, as documented here: https://docs.djangoproject.com/en/1.9/ref/models/expressions/#f-expressions
Specifically, you will want to read the section on "Avoiding race conditions using F()".
You will end up with something along the lines of:
from django.db.models import F
from rest_framework import generics
class ApiDetail(generics.RetrieveUpdateDestroyAPIView):
queryset = Api.objects.all()
serializer_class = ApiSerializer
def get(self, request, *args, **kwargs):
currentApi = self.get_object()
currentApi.currentNumber = F('currentNumber') + 1
currentApi.iterativeField = F('fieldPrefix') + (F('currentNumber') + 1)
currentApi.save()
return super(ApiDetail, self).get(request, *args, **kwargs)
As far as the maxNumberofDigits
, I will leave that as an exercise for the reader. But, I would personally recommend doing an absolute number max, rather than a max number of digits. You could then easily accomplish the above using Case()
/When()
and an F()
. (For example, max 6 digits, the max number would be 999999).
Upvotes: 0