Fix authtoken.TokenProxy error when not installed in Django apps

This commit is contained in:
Terence D. Honles 2020-10-08 08:43:01 -07:00
parent 2e721cdbc8
commit 5777fb5a17
2 changed files with 57 additions and 11 deletions

View File

@ -2,6 +2,7 @@ import binascii
import os import os
from django.conf import settings from django.conf import settings
from django.core.exceptions import ImproperlyConfigured
from django.db import models from django.db import models
from django.utils.translation import gettext_lazy as _ from django.utils.translation import gettext_lazy as _
@ -40,14 +41,31 @@ class Token(models.Model):
return self.key return self.key
class TokenProxy(Token): if 'rest_framework.authtoken' in settings.INSTALLED_APPS:
""" class TokenProxy(Token):
Proxy mapping pk to user pk for use in admin. """
""" Proxy mapping pk to user pk for use in admin.
@property """
def pk(self): @property
return self.user.pk def pk(self):
return self.user.pk
class Meta: class Meta:
proxy = True proxy = True
verbose_name = "token" verbose_name = "token"
else:
def improperly_configured(*args, **kwargs):
raise ImproperlyConfigured(
'"rest_framework.authtoken" must be in your '
'settings.INSTALLED_APPS to use the Token or TokenProxy model.')
# throw improperly_configured when accessing TokenProxy.objects
class Descriptor:
def __get__(self, obj, type=None):
improperly_configured()
class TokenProxy:
def __init__(self, *args, **kwargs):
improperly_configured()
objects = Descriptor()

View File

@ -1,10 +1,13 @@
import importlib
from io import StringIO from io import StringIO
import pytest import pytest
from django.contrib.admin import site from django.contrib.admin import site
from django.contrib.auth.models import User from django.contrib.auth.models import User
from django.core.exceptions import ImproperlyConfigured
from django.core.management import CommandError, call_command from django.core.management import CommandError, call_command
from django.test import TestCase from django.db import models
from django.test import TestCase, modify_settings
from rest_framework.authtoken.admin import TokenAdmin from rest_framework.authtoken.admin import TokenAdmin
from rest_framework.authtoken.management.commands.drf_create_token import \ from rest_framework.authtoken.management.commands.drf_create_token import \
@ -21,6 +24,31 @@ class AuthTokenTests(TestCase):
self.user = User.objects.create_user(username='test_user') self.user = User.objects.create_user(username='test_user')
self.token = Token.objects.create(key='test token', user=self.user) self.token = Token.objects.create(key='test token', user=self.user)
def test_authtoken_can_be_imported_when_not_installed(self):
try:
import rest_framework.authtoken.models
authtoken_models = rest_framework.authtoken.models
assert issubclass(authtoken_models.Token, models.Model)
assert issubclass(authtoken_models.TokenProxy, models.Model)
assert not authtoken_models.Token._meta.abstract
assert authtoken_models.TokenProxy._meta.proxy
with modify_settings(INSTALLED_APPS={
'remove': 'rest_framework.authtoken'}):
importlib.reload(rest_framework.authtoken.models)
authtoken_models = rest_framework.authtoken.models
assert issubclass(authtoken_models.Token, models.Model)
assert authtoken_models.Token._meta.abstract
with pytest.raises(ImproperlyConfigured):
authtoken_models.TokenProxy()
with pytest.raises(ImproperlyConfigured):
authtoken_models.TokenProxy.objects
finally:
# Set the proxy and abstract properties back to the version,
# where authtoken is among INSTALLED_APPS.
importlib.reload(rest_framework.authtoken.models)
def test_model_admin_displayed_fields(self): def test_model_admin_displayed_fields(self):
mock_request = object() mock_request = object()
token_admin = TokenAdmin(self.token, self.site) token_admin = TokenAdmin(self.token, self.site)