【问题标题】:How to perform an update or create in the view using django rest framework?如何使用 django rest 框架在视图中执行更新或创建?
【发布时间】:2017-04-12 10:40:09
【问题描述】:

我正在尝试使用 django 和 django rest 框架创建一个音乐 webapp - 问题在于实现收听记录计数器。每次用户播放歌曲时,该 song_id,user_id 的计数器应该增加。

我的模型是这样的,

class Listen_Record(models.Model):
    number=None
    listen_count = models.IntegerField(default=1,null=True)
    user = models.ForeignKey(User)
    songid = models.ForeignKey(Song)

我的看法,

class ListenRecordCreateAPIView(GenericAPIView,CreateModelMixin,UpdateModelMixin):
    queryset = Listen_Record.objects.all()
    serializer_class = ListenRecordListSerializer



    def put(self,request,*args,**kwargs):
        if Listen_Record.objects.filter(user=request.data['user'], songid=request.data['songid']).exists():

            tableid = Listen_Record.objects.values_list('id', flat=True).filter(user=request.data['user'],
                                                                                songid=request.data['songid']).get()
            cnt = None
            try:
                cnt = Listen_Record.objects.get(id=tableid)
                print(cnt)
            except AttributeError:

                cnt.listen_count = 0

            cnt.listen_count += 1
            print(cnt.listen_count)
            cnt.save(['listen_count'])
        return self.update(cnt,*args,**kwargs)

    def post(self, request, *args, **kwargs):
        if Listen_Record.objects.filter(user=request.data['user'], songid=request.data['songid']).exists():
            self.put(request, *args, **kwargs)
        else:
            return self.create(request,*args,**kwargs)

基本上,默认方法是 POST,但如果 userid 和 songid 存在,它应该 PUT 代替增加 listen_count 字段。我现在得到的错误是“UNIQUE 约束失败:api_listen_record.id”

是否有更优雅的方式来实现此功能或如何修复错误?

编辑:我知道有 update_or_create 方法,但是我如何使用 django rest 框架在 post/put 方法的上下文中使用它?

【问题讨论】:

标签: django python-3.x django-models django-views django-rest-framework


【解决方案1】:

基本上,默认方法是 POST,但如果 userid 和 songid,存在,它应该 PUT 而不是增加listen_count 场地。我现在得到的错误是“唯一约束失败: api_listen_record.id"

这是您的主要问题。前提是客户端发出正确的请求,您作为 API 的工作是验证请求。

如果你真的想强制 PUT 与 POST,那么如果记录存在,并且请求是 POST,你应该拒绝它:

from rest_framework.exceptions import ValidationError

def post(self, request, *args, **kwargs):
    filter = Listen_Record.objects.filter(user=request.data['user'],
                                          songid=request.data['songid'])
    if filter.exists():
        raise ValidationError({'error': 'POST not allowed, send PUT'})
    else:
        return self.create(request,*args,**kwargs)

同样,你的 PUT 方法也应该有这样的检查:

def put(self,request,*args,**kwargs):
    try:
       record = Listen_Record.objects.get(user=request.data['user'],
                                          songid=request.data['songid'])
       record.listen_count = record.listen_count + 1
       record.save()
       return self.update(record,*args,**kwargs)
    except Listen_Record.DoesNotExist:
       raise ValidationError({"error": "Send POST not PUT to create records"})

【讨论】:

  • 谢谢!它现在可以工作了,但是 put 请求给出了一个错误 - “预期的视图 ListenRecordCreateAPIView 将使用名为“pk”的 URL 关键字参数调用。修复你的 URL conf,或正确设置视图上的 .lookup_field 属性。”虽然我的收听次数仍在更新,但很想摆脱错误。
【解决方案2】:

如果你在 django 1 dot 7 上,你可以使用 django 的 update_or_create 方法。 示例取自他们的文档

obj, created = Person.objects.update_or_create(
    first_name='John', last_name='Lennon', defaults=updated_values)

返回一个实例并创建,其中创建的地方实际上是一个布尔值。

也是这个Create Django model or update if exists的骗子

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2016-02-14
    • 2020-05-15
    • 2023-04-08
    • 1970-01-01
    • 2016-05-03
    相关资源
    最近更新 更多