You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Django(DRF)中使用django-rest-knox为非用户模型实例生成令牌的方法

解决方案

django-rest-knox默认提供的AuthToken模型内置了指向Django默认User模型的非空外键约束,所以直接传入非User模型实例创建令牌必然触发字段校验错误。你可以通过两种方案实现需求:

方案1:自定义Knox令牌模型(推荐,灵活度最高)

这种方法完全修改底层令牌的关联逻辑,支持同时兼容用户和其他模型实例的令牌生成:

  1. 首先在项目settings.py中添加配置,指定自定义令牌模型路径,同时禁用knox默认迁移:
# settings.py
INSTALLED_APPS = [
    # ... 其他应用
    # 把knox从INSTALLED_APPS里移除,避免加载默认迁移
    # 'knox',
]
# 替换为你自己的应用名+自定义模型名
KNOX_MODEL = 'your_app_name.CustomAuthToken'
  1. 在你的应用中继承Knox的抽象令牌基类编写自定义模型,添加你需要关联的其他模型外键:
# your_app_name/models.py
from django.db import models
from django.core.exceptions import ValidationError
from knox.models import AbstractAuthToken
# 替换为你要关联的非User模型
from your_app_name.models import YourOtherModel

class CustomAuthToken(AbstractAuthToken):
    # 保留user外键,设置为允许空,兼容原有用户令牌逻辑
    user = models.ForeignKey(
        "auth.User", 
        on_delete=models.CASCADE, 
        null=True, 
        blank=True,
        related_name="auth_tokens"
    )
    # 新增你要关联的其他模型外键
    your_other_instance = models.ForeignKey(
        YourOtherModel,
        on_delete=models.CASCADE,
        null=True,
        blank=True,
        related_name="auth_tokens"
    )

    # 增加校验逻辑,确保令牌至少关联一个实例
    def clean(self):
        super().clean()
        if self.user is None and self.your_other_instance is None:
            raise ValidationError("令牌必须关联用户或其他业务实例")
  1. 执行makemigrations和migrate生成自定义表结构,之后就可以直接为非User实例生成令牌:
from your_app_name.models import CustomAuthToken

# 为非User实例生成令牌,返回值为(令牌对象,明文令牌字符串)
token_obj, token_str = CustomAuthToken.objects.create(your_other_instance=your_instance)
  1. 配套自定义认证类,适配非User实例的认证逻辑:
# your_app_name/auth.py
from knox.auth import TokenAuthentication

class CustomKnoxAuthentication(TokenAuthentication):
    def authenticate_credentials(self, key):
        user, token = super().authenticate_credentials(key)
        # 如果令牌关联的是业务实例,直接返回实例替代用户
        if token.your_other_instance:
            return (token.your_other_instance, token)
        return (user, token)

之后在视图或全局配置中使用这个自定义认证类即可。

方案2:虚拟用户绑定(低侵入,适合小需求)

如果你不想修改Knox的底层逻辑,可以给每个需要生成令牌的非User实例绑定一个专属的无权限虚拟用户:

  1. 在User模型中添加标识字段,区分正常用户和虚拟绑定用户:
# 如果你用的是自定义User模型
class User(AbstractUser):
    is_virtual = models.BooleanField(default=False)
    # 存储关联的非User实例ID
    bound_instance_id = models.IntegerField(null=True, blank=True)
    # 存储关联的模型类型
    bound_instance_type = models.CharField(max_length=50, null=True, blank=True)
  1. 生成令牌时,使用对应绑定的虚拟用户创建即可,认证时再根据虚拟用户的关联字段查询对应的业务实例。

内容的提问来源于stack exchange,提问作者Irfan wani

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.10.03 05:48:03