如何在django-rest-framework的authtoken中更改现有令牌?

 静静我想你啦 发布于 2023-02-09 11:09

保存失败:

from rest_framework.authtoken.models import Token

token = Token.objects.get(user=user1)
token.key = '1'
token.save()

IntegrityError:重复键值违反唯一约束"authtoken_token_user_id_key"

mariodev.. 9

看起来这样可行:

Token.objects.filter(user=user1).update(key='1')


gonz.. 7

我今天遇到了同样的问题,所以我想我应该留下回复,以便将来参考解释为什么会发生这种情况.

keyToken表的主键.

如果您编辑模型实例,则在调用save()django时必须确定是否必须执行INSERT或者执行UPDATE.它是通过在数据库中查找现有行(使用主键)来实现的,因为您只是更改了主键,它将找不到它并假设它必须插入新行.由于您已为该用户提供了一行,并且user_id列具有唯一约束,因此插入将失败.

使用相应生成的sql的示例.

>>> t = Token.objects.get(user=User.objects.get(id=1))
>>> t.key
u'b0750c801a1b075051ed084841f3001bb55dd1f1'
>>> t.key = t.generate_key()
'cafb2efb9b26912d60fc5a0a75b2b7ba0348a2ec'
t.save()

那个save()电话呈现

SELECT (1) AS "a"
  FROM "authtoken_token"
  WHERE "authtoken_token"."key" = 'cafb2efb9b26912d60fc5a0a75b2b7ba0348a2ec'
  LIMIT 1;
INSERT
  INTO "authtoken_token" ("key", "user_id", "created")
  VALUES ('cafb2efb9b26912d60fc5a0a75b2b7ba0348a2ec', 1, '2014-03-18 21:48:30.434677+00:00');

很明显,它SELECT正在寻找带有编辑标记的行(cafb2efb9b26912d60fc5a0a75b2b7ba0348a2ec).

方案:

我想在这个特定情况下你可以删除旧Token实例并创建一个新实例(在单个事务中),它会自动为你生成密钥,如:

token.delete()
Token.objects.create(user=user1)

请注意,这是ORM级别的问题,您可以避免删除/插入,只需更改该行的值但不使用该save()方法.

使用该update()方法是一个很好的选择,因为mariodev建议,你需要手动生成令牌(上面我是如何做的),是的,这将改变主键,关键列,但这是你想要的第一个地方:)

2 个回答
  • 看起来这样可行:

    Token.objects.filter(user=user1).update(key='1')
    

    2023-02-09 11:10 回答
  • 我今天遇到了同样的问题,所以我想我应该留下回复,以便将来参考解释为什么会发生这种情况.

    keyToken表的主键.

    如果您编辑模型实例,则在调用save()django时必须确定是否必须执行INSERT或者执行UPDATE.它是通过在数据库中查找现有行(使用主键)来实现的,因为您只是更改了主键,它将找不到它并假设它必须插入新行.由于您已为该用户提供了一行,并且user_id列具有唯一约束,因此插入将失败.

    使用相应生成的sql的示例.

    >>> t = Token.objects.get(user=User.objects.get(id=1))
    >>> t.key
    u'b0750c801a1b075051ed084841f3001bb55dd1f1'
    >>> t.key = t.generate_key()
    'cafb2efb9b26912d60fc5a0a75b2b7ba0348a2ec'
    t.save()
    

    那个save()电话呈现

    SELECT (1) AS "a"
      FROM "authtoken_token"
      WHERE "authtoken_token"."key" = 'cafb2efb9b26912d60fc5a0a75b2b7ba0348a2ec'
      LIMIT 1;
    INSERT
      INTO "authtoken_token" ("key", "user_id", "created")
      VALUES ('cafb2efb9b26912d60fc5a0a75b2b7ba0348a2ec', 1, '2014-03-18 21:48:30.434677+00:00');
    

    很明显,它SELECT正在寻找带有编辑标记的行(cafb2efb9b26912d60fc5a0a75b2b7ba0348a2ec).

    方案:

    我想在这个特定情况下你可以删除旧Token实例并创建一个新实例(在单个事务中),它会自动为你生成密钥,如:

    token.delete()
    Token.objects.create(user=user1)
    

    请注意,这是ORM级别的问题,您可以避免删除/插入,只需更改该行的值但不使用该save()方法.

    使用该update()方法是一个很好的选择,因为mariodev建议,你需要手动生成令牌(上面我是如何做的),是的,这将改变主键,关键列,但这是你想要的第一个地方:)

    2023-02-09 11:12 回答
撰写答案
今天,你开发时遇到什么问题呢?
立即提问
热门标签
PHP1.CN | 中国最专业的PHP中文社区 | PNG素材下载 | DevBox开发工具箱 | json解析格式化 |PHP资讯 | PHP教程 | 数据库技术 | 服务器技术 | 前端开发技术 | PHP框架 | 开发工具 | 在线工具
Copyright © 1998 - 2020 PHP1.CN. All Rights Reserved 京公网安备 11010802041100号 | 京ICP备19059560号-4 | PHP1.CN 第一PHP社区 版权所有