我有一个 View 集,用户可以在其中为特定产品创建评论并列出他们为所有产品创建的所有评论:
class ProductReviewViewset(CreateModelMixin, ListModelMixin, GenericViewSet):
serializer_class = ProductReviewSerializer
def get_queryset(self):
# Return all reviews for user that are not marked as deleted
user = self.request.user
return ProductReview.objects.filter(user=user, deleted=False).order_by('review__name')
def perform_create(self, serializer):
# Add user to review object before saving
user = self.request.user
serializer.save(user=self.request.user)
问题在于,这允许用户为同一对象创建多个评论。我想防止这种情况发生,并且只允许在没有为该产品创建其他评论的情况下创建评论(标记为“已删除”的评论将不被计算在内)。
到目前为止,我能够重写 .create() 方法并在其中进行序列化、验证和检查重复项。
class ProductReviewViewset(CreateModelMixin, ListModelMixin, GenericViewSet):
serializer_class = ProductReviewSerializer
def get_queryset(self):
# Return all reviews for user that are not marked as deleted
user = self.request.user
return ProductReview.objects.filter(user=user, deleted=False).order_by('review__name')
def create(self, request, *args, **kwargs):
# Override create method to prevent duplicate object creation
serializer = ProductReviewSerializer(data=self.request.data)
serializer.is_valid(raise_exception=True)
user = self.request.user
product = serializer.validated_data['product']
exists = ProductReview.objects.filter(user=user, product=product, deleted=False).exists()
if not exists:
serializer.save(user=user)
return Response(status=status.HTTP_201_CREATED)
else:
return Response(status=status.HTTP_409_CONFLICT)
有没有更简单或更好的方法来做到这一点?或者这是这样做的方法吗?
谢谢!
最佳答案
另一种方法是使用get_or_create
查询集方法:get_or_create
def create(self, request, *args, **kwargs):
# Override create method to prevent duplicate object creation
serializer = ProductReviewSerializer(data=self.request.data)
serializer.is_valid(raise_exception=True)
user = self.request.user
product = serializer.validated_data['product']
obj, created = ProductReview.objects.get_or_create(user=user, product=product, deleted=False, defaults=seriaizer.validated_data)
if not created:
serializer.save(user=user)
return Response(status=status.HTTP_201_CREATED)
else:
return Response(status=status.HTTP_409_CONFLICT)
并行发出请求时,get_or_create
将防止竞争条件
关于Django休息框架: Prevent duplicate objects when using CreateModelMixin,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/62380410/