【问题标题】:Delete or Update if 3 object existed at the same time - Django Rest Framework如果同时存在 3 个对象,则删除或更新 - Django Rest Framework
【发布时间】:2017-11-27 09:54:32
【问题描述】:

我正在为我的博客网站构建 LIKE、UNLIKE 和 CLAPPING 功能。我有这样的模型: 模型反应(喜欢、不喜欢和鼓掌)

class Reaction(models.Model):
    REACT_TYPES = (
        (LIKE, 'Like'),
        (CLAPPING, 'Clapping')
    )
    user = models.ForeignKey(User)
    react_type = models.CharField(max_length=100, choices=REACT_TYPES, default='LIKE')
    timestamp = models.DateTimeField(auto_now_add=True, null=True)
    content_type = models.ForeignKey(ContentType, on_delete=models.CASCADE, null=True)
    object_id = models.PositiveIntegerField(null=True)
    content_object = GenericForeignKey('content_type', 'object_id')

    class Meta:
        unique_together = ('user', 'content_type', 'object_id')

序列化器模型 REACTION 从模型导入反应

class ReactCreateUpdateSerializer(ModelSerializer):
    class Meta:
        model = Reaction
        fields = [
            'user',
            'react_type',
            'content_type',
            'object_id',
        ] 

我的 REACT 视图集:

from rest_framework.generics import CreateAPIView
class ReactCreateAPIView(CreateAPIView):
    queryset = Reaction.objects.all()
    serializer_class = ReactCreateUpdateSerializer

我假设之前创建了一个带有 LIKE 的对象。我想构建一个函数可以做这些事情:

  • 如果用户再次使用存在 4 个对象的 POST 方法:user, content_type, object_id, react_type=LIKE。它成为删除对象。 (不喜欢)。然后,如果再发布一个,它将再次成为创建对象。 (喜欢)
  • 如果用户使用存在 4 个对象的 POST 方法:user, content_type, object_id, react_type=CLAPPING。它变为使用更新 2 字段更新数据库中的可用反应:react_type 和时间戳,所有其他字段均未更改。

我认为这是每个人在为网站构建 API 需要反应时都会遇到的问题。所以希望您的热心帮助。提前致谢!

【问题讨论】:

  • 无需删除记录,如果该用户已经喜欢,您只需更新其react_type= UNLIKE
  • 我可以更新 models.py 或 serializers.py 中的 def 吗?有没有一个例子@Satendra

标签: django django-models django-rest-framework


【解决方案1】:

您只需在请求数据中发送react_type, 如果您将 @detail_route 创建为 pkobject_id 将始终存在,如果用户以 身份登录,user 对象将在请求中可用request.user

任何用户的反应对象都将在该用户提出第一个请求时创建。

不需要删除记录,如果用户已经LIKED,则必须更新反应对象react_type=UNLIKE

class PostViewSet(viewsets.ModelViewSet):
    # Data model on which user is reacting
    queryset = Post.objects.all()
    serializer_class = PostSerializer

    @detail_route(methods=['post'])
    def react(self, request, pk=None):

        react_type = request.data['react_type']
        obj = self.get_object()

        # GenericForeignKey does not support get_or_create
        try:
            reaction_obj = Reaction.objects.get(content_type=ContentType.objects.get_for_model(obj), object_id=obj.id, user=request.user)  
            reaction_obj.react_type = react_type
            reaction_obj.save()
        except Reaction.DoesNotExist:
            obj.reactions.create(user=request.user, react_type=react_type)

        return Response({'success': True})

用户反应的模型应该具有多态连接

class Post(models.Model)
    # Other fields
    ...
    reactions = GenericRelation(Reaction, related_query_name='posts')

将您的视图注册为

url(r'^posts/(?P<pk>[0-9]+)/$', PostViewSet.as_view(), name='post-reaction')
# http://domian.com/api/v1/posts/1/react 
# method: POST
# data : {'react_type': 'UNLIKE'}
# content-type: 'application/json'

【讨论】:

  • 谢谢,我真的不明白。但是我在您的代码中使用 CreateAPIView 而不是 ModelViewSet 。而且我在 Post 中没有反应字段。如何修复您的代码?
  • 您必须在您的帖子模型中创建一个反应字段,正如您提到的,您使用的是 drf,我已经为您提供了 viewset 的示例。您可以将您的观点添加到问题中吗?我会相应地更新我的答案
  • 我使用 ContentType 与 Post Model 建立连接。我更新了视图集。希望您的帮助!
  • CreateAPIView 在这种情况下将不起作用,您必须按照我在答案中解释的那样使用 ModelViewSet 并相应地更新 url。
  • 您的代码工作成功,但它继续创建 obj 而不是更新旧的。我认为 PostViewSet 有问题
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2014-12-14
  • 1970-01-01
  • 1970-01-01
  • 2018-01-08
  • 1970-01-01
  • 1970-01-01
  • 2013-01-09
相关资源
最近更新 更多