我有一个带有@BEFORE_CREATE信号钩子的模型,如下所示:
from django.lifecycle.hooks import BEFORE_CREATE
class Item(models.Model):
title = models.CharField()
slug = models.JSONField(unique=True)
@hook(BEFORE_CREATE)
def populate_slug(self):
# Create a slug from the title
# If the slug already exists, append "-{n}"
# to make sure it is unique
slug[0] = slugify(self.title)
n = 2
while List.objects.filter(slug=slug).exists():
slug[0] = f"{slug[0]-{n}"
n += 1
self.slug = slug
在我的测试中,当项目一个接一个同步创建时,这工作得很好:
i1 = Item.objects.create(title="Hello")
i2 = Item.objects.create(title="Hello")
self.assertEqual(i1.slug, ["hello"])
self.assertEqual(i2.slug, ["hello-2"])
然而,在我的实际前端,我异步创建这些对象,同时:
const item1 = axios.post(POST_ITEMS_URL, {title: "Hello"})
const item2 = axios.post(POST_ITEMS_URL, {title: "Hello"})
Promise.all([item1, item2]);
这给了我这个错误:
web_1 | django.db.utils.IntegrityError: duplicate key value violates unique constraint "app_item_slug_key"
web_1 | DETAIL: Key (slug)=(["hello"]) already exists.
一个简单的修复(我认为)将我的@hook更改为AFTER_CREATE,但我想避免对所有对象进行额外的写入,如果可能的话。
有可能把一个例外的IntegrityError某处?如果有,在哪里?
或者我还能怎么克服这个问题?
我正在使用PostGRE。
通过重写Item视图的create方法,找出放置IntegrityError的位置:
# To retry 3 times
def create(self, request, *args, **kwargs):
n = 0
while n < 4:
try:
serializer = self.get_serializer(data=request.data)
serializer.is_valid(raise_exception=True)
self.perform_create(serializer)
headers = self.get_success_headers(serializer.data)
return Response(
serializer.data, status=status.HTTP_201_CREATED, headers=headers
)
except IntegrityError:
n += 1
continue
break
Async post在前端现在工作:)