我已经阅读了很多与clashes reverse accessor
相关的问题,但似乎没有什么帮助我。
我正在尝试自定义Token
中的DRF
字段,以便能够向其中添加一些字段(我希望每个Token
有一个Company
, Companies
可以创建FiscalEntities
,每个FiscalEntity
都有自己的Token
)
我关注了以下问题:How to use custom token model in Django Rest Framework
核心/型号
from django.db import models
from django.utils.translation import ugettext_lazy as _
from rest_framework import authentication
from company.models import Company
from fiscalentity.models import FiscalEntity
class CustomAuthenticationToken(models.Model):
"""
The default authorization token model.
"""
key = models.CharField(_("Key"), max_length=40, primary_key=True)
company = models.OneToOneField(
Company, related_name='auth_token',
on_delete=models.CASCADE, verbose_name=_("Company")
)
created = models.DateTimeField(_("Created"), auto_now_add=True)
# Fiscal entity can be null because if it is null this token belongs to the parent Company
fiscal_entity = models.ForeignKey(FiscalEntity, null=True, on_delete=models.CASCADE)
class Meta:
verbose_name = _("Token")
verbose_name_plural = _("Tokens")
def save(self, *args, **kwargs):
if not self.key:
self.key = self.generate_key()
return super(CustomAuthenticationToken, self).save(*args, **kwargs)
@staticmethod
def generate_key():
return binascii.hexlify(os.urandom(20)).decode()
def __str__(self):
return self.key
class BearerAuthentication(authentication.TokenAuthentication):
"""
Simple token based authentication using utvsapitoken.
Clients should authenticate by passing the token key in the 'Authorization'
HTTP header, prepended with the string 'Bearer '. For example:
Authorization: Bearer 956e252a-513c-48c5-92dd-bfddc364e812
"""
keyword = 'Bearer'
model = CustomAuthenticationToken
核心/身份验证
from rest_framework.authentication import TokenAuthentication
from core.models import CustomAuthenticationToken
class CustomTokenAuthentication(TokenAuthentication):
model = CustomAuthenticationToken
应用/设置
INSTALLED_APPS = [
...
'rest_framework',
'rest_framework.authtoken',
'core',
...
]
REST_FRAMEWORK = {
'DEFAULT_PAGINATION_CLASS': 'rest_framework.pagination.PageNumberPagination',
'PAGE_SIZE': 5,
'DEFAULT_AUTHENTICATION_CLASSES': (
'core.models.BearerAuthentication',
'core.authentication.CustomTokenAuthentication'
),
}
AUTHENTICATION_BACKENDS = [
'core.models.BearerAuthentication',
]
尝试运行迁移时出现以下错误:
authtoken.Token.user: (fields.E304) Reverse accessor for 'Token.user' clashes with reverse accessor for 'CustomAuthenticationToken.company'.
HINT: Add or change a related_name argument to the definition for 'Token.user' or 'CustomAuthenticationToken.company'.
authtoken.Token.user: (fields.E305) Reverse query name for 'Token.user' clashes with reverse query name for 'CustomAuthenticationToken.company'.
HINT: Add or change a related_name argument to the definition for 'Token.user' or 'CustomAuthenticationToken.company'.
core.CustomAuthenticationToken.company: (fields.E304) Reverse accessor for 'CustomAuthenticationToken.company' clashes with reverse accessor for 'Token.user'.
HINT: Add or change a related_name argument to the definition for 'CustomAuthenticationToken.company' or 'Token.user'.
core.CustomAuthenticationToken.company: (fields.E305) Reverse query name for 'CustomAuthenticationToken.company' clashes with reverse query name for 'Token.user'.
HINT: Add or change a related_name argument to the definition for 'CustomAuthenticationToken.company' or 'Token.user'.
我尝试省略
company = models.OneToOneField(
Company, related_name='auth_token',
on_delete=models.CASCADE, verbose_name=_("Company")
)
但是这样做,我收到一个新错误,说Invalid field name(s) given in select_related: 'user'. Choices are: (fiscal_entity)
谢谢您的帮助
答案 0 :(得分:1)
我遵循的答案(How to use custom token model in Django Rest Framework)适用于具有默认Custom Tokens
实现的Token
。由于我正在使用BearerAuthentication
,因此我需要重写从authenticate_credentials
继承的方法TokenAuthentication
。最后,我的结局BearerAuthentication
如下所示:
class BearerAuthentication(authentication.TokenAuthentication):
"""
Simple token based authentication using utvsapitoken.
Clients should authenticate by passing the token key in the 'Authorization'
HTTP header, prepended with the string 'Bearer '. For example:
Authorization: Bearer 956e252a-513c-48c5-92dd-bfddc364e812
"""
keyword = 'Bearer'
model = CustomAuthenticationToken
def authenticate_credentials(self, key):
model = self.get_model()
try:
token = model.objects.select_related('company').get(key=key)
except model.DoesNotExist:
raise exceptions.AuthenticationFailed(_('Invalid token.'))
if not token.company.is_active:
raise exceptions.AuthenticationFailed(_('User inactive or deleted.'))
return token.company, token