django - Django Rest Framework - “unique_together”内部服务器错误。如何响应错误
问题描述
我目前有一个名为“评论”的模型,其中我有一个“unique_together”约束,因此一个用户每篇文章只能写一篇评论。
class Review(models.Model):
created = models.DateTimeField(auto_now_add=True)
user = models.ForeignKey(User, related_name='reviews', on_delete=models.SET_NULL, null=True)
post = models.ForeignKey(Post, related_name='reviews', on_delete=models.CASCADE)
rating = models.IntegerField()
comment = models.TextField(blank=True, null=True)
class Meta:
unique_together = ['user', 'post']
在我的视图中,我从请求中获取用户(我正在使用令牌身份验证)并使用该用户通过覆盖“perform_create”方法来保存对象:
class ReviewCreateView(CreateAPIView):
permission_classes = [IsAuthenticated]
serializer_class = ReviewCreateSerializer
def perform_create(self, serializer):
serializer.save(user=self.request.user)
我的序列化器看起来像这样:
class ReviewCreateSerializer(ModelSerializer):
class Meta:
model = Review
fields = ['post', 'rating', 'comment']
当我尝试向同一用户的同一帖子提交两条评论时,我收到内部服务器错误。
我的 HTTP POST 请求的正文如下所示:
{
"post" : 11,
"rating": 1,
"comment": "this is a great post"
}
而不是得到错误响应(例如 403 错误)。我得到了这个 Django 服务器错误:
django.db.utils.IntegrityError: duplicate key value violates unique constraint
在花了一些时间研究之后,我看到 Django Rest Framework 提供了“UniqueTogetherValidator”。所以我像这样添加它:
class ReviewCreateSerializer(ModelSerializer):
class Meta:
model = Review
fields = ['post', 'rating', 'comment']
validators = [
UniqueTogetherValidator(
queryset=Review.objects.all(),
fields=['user', 'post']
)
]
但是我遇到的问题是它出错,因为它找不到关键的“用户”,我猜是因为我的 HTTP 请求正文中没有“用户”字段(因为用户被抓住了Django 使用身份验证令牌)。我收到以下错误:
KeyError: 'user'
我还尝试将“用户”添加到我的序列化器字段中:
fields = ['user', 'post', 'rating', 'comment']
但我收到以下错误响应:
{
"user": [
"This field is required."
]
}
我真的很感激一些帮助来解决这个问题。非常感谢!
解决方案
尝试使用CurrentUserDefault序列化程序字段,以便可以隐式检索用户以进行验证。
class ReviewCreateSerializer(ModelSerializer):
user = serializers.HiddenField(
default=serializers.CurrentUserDefault()
)
class Meta:
model = Review
fields = fields = ['user', 'post', 'rating', 'comment']
validators = [
UniqueTogetherValidator(
queryset=Review.objects.all(),
fields=['user', 'post']
)
]
此外,有了这个,您不再需要将用户传递给序列化程序保存方法,因为它已经存在于序列化程序中。因此,您可以摆脱perform_create()
视图中的覆盖方法
推荐阅读
- python - 如何使用 Python 和 Flask 用 ROOT 定义“p”
- python - BeautifulSoup 没有使用 CSS 选择器返回所有元素
- javascript - 内联时未定义javascript变量
- php - Wordpress 博客分页
- python - 如何删除特定单词之前的所有文本?
- r - 如何在每个像素的大型光栅堆栈上运行 Mann-Kendall 趋势测试?
- python - 为什么导入 uuid 会导致 uwsgi 守护进程挂起?
- express - Next.js-Passport 登录成功后如何获取用户数据?【客户端路由】
- dart - 如何在循环中创建地图?
- android - 如何让我的应用程序使用导航视图运行?