Search code examples
pythondjangodjango-testingdjango-tests

Django test matching query does not exist


I'm new to Django. I am building an app that requires a lot of control over user access to various use and features.

For this I created a model called 'UserType' that has some user groups as objects i.e. scanner, overwatch, lancer and admin.

Another model, AssignedType, assigns users to one or more UserType. It has two fields. 'user' which is related to User model and 'user_type' which is related to UserType model.

The file which controls access rights (rights.py) is as follows:

from .models import User, UserType, AssignedType 

# Get all user types in the database as model objects
scanner = UserType.objects.get(id=1)
overwatch = UserType.objects.get(id=2)
lancer = UserType.objects.get(id=3)
admin = UserType.objects.get(id=4)

# Rights of each type of user. Keys are the views and values are the user types allowed to access a particular view
group_rights = {
    'scanner':[scanner, admin],
}

# Function to determine whether the logged user may access a view. Returns True if allowed. False otherwise.
def is_user_permitted(logged_user, view):
    
    # Get a list of users types assigned to the user
    assigned_types_objects = AssignedType.objects.all().filter(user=logged_user)
    assigned_types = []
    for assigned_type in assigned_types_objects:
        assigned_types.append(assigned_type.user_type)
    
    # Get a list of users types permitted to access the view.
    view_rights = group_rights[view]

    # Check whether there is any user type is common in the two lists. If so, user is authorized to access the view. 
    if set(assigned_types) & set(view_rights):
        return True
    else:
        return False

And the view that calls the function in the above file is as follows:

@login_required
def scanner(request):
    if not is_user_permitted(request.user, 'scanner'):
        raise PermissionDenied

    return render(request, "DataMech/scanner.html")

Everything appears to be working fine. However I am receiving an error when I try to create and run a test. Following is my tests.py file.

from django.test import TestCase, Client
from django.urls import reverse
from DataMech.models import User, UserType, AssignedType 

class TestScanner(TestCase):
    def setUp(self):
        User.objects.create(username='scanner1', password='abc')
        User.objects.create(username='scanner2', password='abc')
        User.objects.create(username='overwatch1', password='abc')
        User.objects.create(username='overwatch2', password='abc')
        User.objects.create(username='lancer1', password='abc')
        User.objects.create(username='lancer2', password='abc')
        User.objects.create(username='lancer3', password='abc')
        User.objects.create(username='lancer4', password='abc')
        User.objects.create(username='admin1', password='abc')
        UserType.objects.create(name='scanner')
        UserType.objects.create(name='overwatch')
        UserType.objects.create(name='lancer')
        UserType.objects.create(name='admin')
        AssignedType.objects.create(user='scanner1', user_type='scanner')
        AssignedType.objects.create(user='scanner2', user_type='scanner')
        AssignedType.objects.create(user='overwatch1', user_type='overwatch')
        AssignedType.objects.create(user='overwatch2', user_type='overwatch')
        AssignedType.objects.create(user='lancer1', user_type='lancer')
        AssignedType.objects.create(user='lancer2', user_type='lancer')
        AssignedType.objects.create(user='lancer3', user_type='lancer')
        AssignedType.objects.create(user='lancer4', user_type='lancer')
        AssignedType.objects.create(user='admin1', user_type='admin')

    def test_allow_access_only_if_user_is_authorized_GET(self):

        c = Client()
        c.login(username='scanner1', password='abc')
        response = c.get(reverse('scanner'))
        self.assertEquals(response.status_code, 200)
        self.assertTemplateUsed(response, 'DataMech/scanner.html')
        c.logout()

        c = Client()
        c.login(username='scanner2', password='abc')
        response = c.get(reverse('scanner'))
        self.assertEquals(response.status_code, 200)
        self.assertTemplateUsed(response, 'DataMech/scanner.html')
        c.logout()

        c = Client()
        c.login(username='overwatch1', password='abc')
        response = c.get(reverse('scanner'))
        self.assertEquals(response.status_code, 403)
        c.logout()

Running this test causes the following error.

Traceback (most recent call last):
  File "C:\Users\Dell\Desktop\Financial reports project\FinData\FinData\manage.py", line 22, in <module>
    main()
  File "C:\Users\Dell\Desktop\Financial reports project\FinData\FinData\manage.py", line 18, in main
    execute_from_command_line(sys.argv)
  File "C:\Python39\lib\site-packages\django\core\management\__init__.py", line 401, in execute_from_command_line
    utility.execute()
  File "C:\Python39\lib\site-packages\django\core\management\__init__.py", line 395, in execute
    self.fetch_command(subcommand).run_from_argv(self.argv)
  File "C:\Python39\lib\site-packages\django\core\management\commands\test.py", line 23, in run_from_argv
    super().run_from_argv(argv)
  File "C:\Python39\lib\site-packages\django\core\management\base.py", line 330, in run_from_argv
    self.execute(*args, **cmd_options)
  File "C:\Python39\lib\site-packages\django\core\management\base.py", line 371, in execute
    output = self.handle(*args, **options)
  File "C:\Python39\lib\site-packages\django\core\management\commands\test.py", line 53, in handle
    failures = test_runner.run_tests(test_labels)
  File "C:\Python39\lib\site-packages\django\test\runner.py", line 698, in run_tests
    self.run_checks(databases)
  File "C:\Python39\lib\site-packages\django\test\runner.py", line 636, in run_checks
    call_command('check', verbosity=self.verbosity, databases=databases)
  File "C:\Python39\lib\site-packages\django\core\management\__init__.py", line 168, in call_command
    return command.execute(*args, **defaults)
  File "C:\Python39\lib\site-packages\django\core\management\base.py", line 371, in execute
    output = self.handle(*args, **options)
  File "C:\Python39\lib\site-packages\django\core\management\commands\check.py", line 63, in handle
    self.check(
  File "C:\Python39\lib\site-packages\django\core\management\base.py", line 392, in check
    all_issues = checks.run_checks(
  File "C:\Python39\lib\site-packages\django\core\checks\registry.py", line 70, in run_checks
    new_errors = check(app_configs=app_configs, databases=databases)
  File "C:\Python39\lib\site-packages\django\core\checks\urls.py", line 13, in check_url_config
    return check_resolver(resolver)
  File "C:\Python39\lib\site-packages\django\core\checks\urls.py", line 23, in check_resolver
    return check_method()
  File "C:\Python39\lib\site-packages\django\urls\resolvers.py", line 408, in check
    for pattern in self.url_patterns:
  File "C:\Python39\lib\site-packages\django\utils\functional.py", line 48, in __get__
    res = instance.__dict__[self.name] = self.func(instance)
  File "C:\Python39\lib\site-packages\django\urls\resolvers.py", line 589, in url_patterns
    patterns = getattr(self.urlconf_module, "urlpatterns", self.urlconf_module)
  File "C:\Python39\lib\site-packages\django\utils\functional.py", line 48, in __get__
    res = instance.__dict__[self.name] = self.func(instance)
  File "C:\Python39\lib\site-packages\django\urls\resolvers.py", line 582, in urlconf_module
    return import_module(self.urlconf_name)
  File "C:\Python39\lib\importlib\__init__.py", line 127, in import_module
    return _bootstrap._gcd_import(name[level:], package, level)
  File "<frozen importlib._bootstrap>", line 1030, in _gcd_import
  File "<frozen importlib._bootstrap>", line 1007, in _find_and_load
  File "<frozen importlib._bootstrap>", line 986, in _find_and_load_unlocked
  File "<frozen importlib._bootstrap>", line 680, in _load_unlocked
  File "<frozen importlib._bootstrap_external>", line 790, in exec_module
  File "<frozen importlib._bootstrap>", line 228, in _call_with_frames_removed
  File "C:\Users\Dell\Desktop\Financial reports project\FinData\FinData\FinData\urls.py", line 21, in <module>
    path("", include("DataMech.urls")),
  File "C:\Python39\lib\site-packages\django\urls\conf.py", line 34, in include
    urlconf_module = import_module(urlconf_module)
  File "C:\Python39\lib\importlib\__init__.py", line 127, in import_module
    return _bootstrap._gcd_import(name[level:], package, level)
  File "<frozen importlib._bootstrap>", line 1030, in _gcd_import
  File "<frozen importlib._bootstrap>", line 1007, in _find_and_load
  File "<frozen importlib._bootstrap>", line 986, in _find_and_load_unlocked
  File "<frozen importlib._bootstrap>", line 680, in _load_unlocked
  File "<frozen importlib._bootstrap_external>", line 790, in exec_module
  File "<frozen importlib._bootstrap>", line 228, in _call_with_frames_removed
  File "C:\Users\Dell\Desktop\Financial reports project\FinData\FinData\DataMech\urls.py", line 4, in <module>
    from . import views
  File "C:\Users\Dell\Desktop\Financial reports project\FinData\FinData\DataMech\views.py", line 12, in <module>
    from .rights import is_user_permitted
  File "C:\Users\Dell\Desktop\Financial reports project\FinData\FinData\DataMech\rights.py", line 4, in <module>
    scanner = UserType.objects.get(id=1)
  File "C:\Python39\lib\site-packages\django\db\models\manager.py", line 85, in manager_method
    return getattr(self.get_queryset(), name)(*args, **kwargs)
  File "C:\Python39\lib\site-packages\django\db\models\query.py", line 429, in get
    raise self.model.DoesNotExist(
DataMech.models.DoesNotExist: UserType matching query does not exist.

What am I doing wrong here?


Solution

  • In your views you import the rights.py file. When your tests start there is no UserType instances created. When Django tries to set up so that it can start your tests it gets this error because of this fact. You should use the get_or_create method instead to ensure that the objects are created:

    scanner, created = UserType.objects.get_or_create(name='scanner')
    

    And so on. You should also adjust your tests for this by not creating the objects there or using this method.