我正致力于通过Django Rest Framework在移动应用API的API中实现Like / Different功能。
所以我有以下型号:
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')
的url:
router.register(r'likes', views.LikesView, 'likes')
为了喜欢播放列表,我发送POST
方法与正文playlist = 19
,user = 3
,like = 1
。喜欢成功创造。
与不同的播放列表不同,我发送PUT
方法与正文:playlist = 19
,user = 3
,但我收到了以下错误:
“non_field_errors”:[ “字段用户,播放列表必须创建一个唯一的集合。” ]
我理解它是因为模型中的unique_together
而发生的。但我没有创建具有相同user
和playlist
的新记录。我只想更新现有记录。为什么会发生这种情况以及如何解决这个问题?
答案 0 :(得分: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)
您没有提供实例参数,默认为None。
对于更新,仅当实例属性不是None:
时,才应跳过unique_together验证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)