【问题标题】:unique_together is not allowing to update recordunique_together 不允许更新记录
【发布时间】:2015-07-27 16:35:11
【问题描述】:

我正在通过 Django Rest Framework 在移动应用程序 API 中实现 Like/Unlike 功能。

所以我有以下模型:

class PlaylistLikes(models.Model):
    user = models.ForeignKey(User)
    playlist = models.ForeignKey(Playlist)
    like = models.BooleanField(default=0, blank=True)

    class Meta:
        unique_together = ('user', 'playlist',)
        verbose_name = "Playlist like"
        verbose_name_plural = "Playlist likes"

我添加了unique_together 以限制用户喜欢他已经喜欢的播放列表。

我的看法:

class LikesView(viewsets.ModelViewSet):
    queryset = PlaylistLikes.objects.all()
    serializer_class = LikesSerializer
    filter_backends = (filters.OrderingFilter, filters.DjangoFilterBackend, filters.SearchFilter)
    filter_class = LikesFilter

    search_fields = ('playlist', 'user',)

    def create(self, request, *args, **kwargs):
        user = request.user
        request.data['user'] = user.pk
        serializer = self.get_serializer(data=request.data)
        serializer.is_valid(raise_exception=True)
        self.perform_create(serializer)
        return Response(serializer.data, status=status.HTTP_201_CREATED)

    @detail_route(methods=['put'])
    def put(self, request, *args, **kwargs):
        user = request.user
        request.data['user'] = user.pk
        serializer = self.get_serializer(data=request.data)
        serializer.is_valid(raise_exception=True)
        self.perform_update(serializer)
        return Response(serializer.data, status=status.HTTP_200_OK)

和序列化器:

class LikesSerializer(serializers.ModelSerializer):

    def create(self, validated_data):
        like = PlaylistLikes.objects.create(**validated_data)
        playlist = Playlist.objects.get(pk=like.playlist.id)
        playlist.likes_count += 1
        playlist.save()
        return validated_data

    def update(self, instance, validated_data):
        like = PlaylistLikes.objects.get(**validated_data)
        like.like = False
        like.save()
        playlist = Playlist.objects.get(pk=like.playlist.id)
        playlist.likes_count -= 1
        playlist.save()
        return validated_data

    class Meta:
        model = PlaylistLikes
        fields = ('user', 'playlist', 'like')

网址:

router.register(r'likes', views.LikesView, 'likes')

为喜欢播放列表,我发送POST 方法和正文playlist = 19user = 3like = 1。 Like 已成功创建。 与相同的播放列表不同,我发送 PUT 方法,正文为:playlist = 19user = 3,但出现以下错误:

“non_field_errors”:[ “字段用户,播放列表必须设置唯一。” ]

我知道这是因为模型中的unique_together 而发生的。但我没有创建具有相同userplaylist 的新记录。我只想更新现有记录。为什么会发生这种情况以及如何解决这个问题?

【问题讨论】:

  • 嗯...我发现我可以在播放列表被喜欢时返回 Id (fields = ('id', 'user', 'playlist', 'like'))。我们决定不更新记录,而只是删除它。因此,正在构建移动应用程序的人可以使用此 ID 来不同于播放列表。他只是将DELETE 方法发送到/api/likes/*like_id*

标签: python django api django-rest-framework


【解决方案1】:

这是因为在 PUT 方法处理程序中,您创建了一个序列化程序而不指定实例:

serializer = self.get_serializer(data=request.data)

Serializer.__init__()

def __init__(self, instance=None, data=empty, **kwargs):
    self.instance = instance
    if data is not empty:
        self.initial_data = data
    self.partial = kwargs.pop('partial', False)
    self._context = kwargs.pop('context', {})
    kwargs.pop('many', None)
    super(BaseSerializer, self).__init__(**kwargs)

您没有提供实例参数,它默认为无。

对于更新,应跳过 unique_together 验证,仅当实例属性不是 None 时:

class UniqueTogetherValidator(object):
    def exclude_current_instance(self, attrs, queryset):
        """
        If an instance is being updated, then do not include
        that instance itself as a uniqueness conflict.
        """
        if self.instance is not None:
            return queryset.exclude(pk=self.instance.pk)
        return queryset

为了解决这个问题,可以在初始化序列化器之前移动Userlikes对象的查询:

like = PlaylistLikes.objects.get(**query)
serializer = self.get_serializer(like, data=request.data)

【讨论】:

  • 我正在按照您的解释进行操作,但在方法 exclude_current_instance 中出现 QuerySet' object has no attribute 'pk' 错误
猜你喜欢
  • 2010-10-30
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2019-05-18
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多