简体   繁体   中英

psycopg2.errors.UndefinedTable: relation “exercises” does not exist - Django Testing

I started writing my first tests in django. I have problem with testing POST method based on model.

My project tree looks:

-   db.sqlite3
-   manage.py
-   tree.txt
-   
----api
-   -   admin.py
-   -   apps.py
-   -   models.py
-   -   serializers.py
-   -   urls.py
-   -   views.py
-   -   __init__.py
-   -   
-   ----migrations
-   -   -   0001_initial.py
-   -   -   __init__.py
-   -   -   
-   -           
-   ----tests
-   -   -   test_models.py
-   -   -   test_urls.py
-   -   -   test_views.py
-   -   -   __init__.py
-   -   -   
-   -           
-           
----drummingpractice
-   -   asgi.py
-   -   settings.py
-   -   urls.py
-   -   wsgi.py
-   -   __init__.py
-   -   
-           
----frontend
-   -   admin.py
-   -   apps.py
-   -   models.py
-   -   urls.py
-   -   views.py
-   -   __init__.py
-   -   
-   ----migrations
-   -   -   __init__.py
-   -   -   
-   -           
-   ----templates
-   -   ----frontend
-   -           exercises_catalog.html
-   -           exercise_add.html
-   -           workouts_history.html
-   -           workouts_stats.html
-   -           workout_add.html
-   -           
-   ----tests
-   -   -   test_models.py
-   -   -   test_urls.py
-   -   -   test_views.py
-   -           
-           
----static

I writing tests for app 'frontend'. I tried test function 'add_exercises'

frontend.views.py

def add_exercise(request):
    if request.method == 'POST':
        data = request.POST
        how_many_img = len(request.FILES.getlist('images'))
        next_exercise_id = Exercises.objects.values('exercise_id').order_by('-exercise_id')[0]['exercise_id'] + 1

        # selected module
        if data['module'] != 'none':
            img_path = '/exercises_img/{module_id}/{exercise_id}/'.format(module_id=data['module'],
                                                                          exercise_id=next_exercise_id)
            module_id = data['module']

        # create new module
        elif data['module_new'] != '':
            Modules.objects.get_or_create(module_name=data['module_new'])   # insert modules...
            new_module_id = Modules.objects.values('module_id').get(module_name=data['module_new'])['module_id']   # get newest module_id
            img_path = '/exercises_img/{module_id}/{exercise_id}/'.format(module_id=new_module_id,
                                                                          exercise_id=next_exercise_id)
            module_id = new_module_id
        else:
            return HttpResponse('Select existing module or create new')

        result = upload_file(request=request, module_id=module_id, exercise_id=next_exercise_id)

        if result:
            # change format dd/mm/YYYY HH:SS -> dd-mm-YYYY HH:SS
            lesson_datetime_normalized = data['lesson_datetime'].replace('/', '-')

            exercise = Exercises.objects.create(
                exercise_name=data['exercise_name'],
                module=Modules.objects.get(module_id=module_id),
                lesson_datetime=lesson_datetime_normalized,
                lesson_tempo=data['lesson_tempo'],
                img_path=img_path,
                note=data['note'],
                how_many_img=how_many_img
            )
            return redirect('catalog')
        else:
            return HttpResponse('Something wrong with upload image')
    elif request.method == 'GET':
        print('jestem w get')
        #modules = Modules.objects.all().order_by('module_id')
        modules = Modules.objects.raw(
        'select * from modules order by module_id asc;')

        context = {'modules': modules}
        return render(request, 'frontend/exercise_add.html', context)

My 'test_views.py' file in frontend app looks like:

frontend.tests.test_views.py

from django.test import TestCase, Client
from django.urls import reverse

from django.apps import apps
Modules = apps.get_model('api', 'Modules')
Exercises = apps.get_model('api', 'Exercises')
Workouts = apps.get_model('api', 'Workouts')

class TestViews(TestCase):

    def setUp(self):
        self.client = Client()
        self.catalog_url = reverse('catalog')
        self.workouts_url = reverse('workouts')
        self.stats_url = reverse('stats')
        self.add_exercise_url = reverse('exercise-add')

    def test_catalog_GET(self):
        response = self.client.get(self.catalog_url)

        self.assertEqual(response.status_code, 200)
        self.assertTemplateUsed(response, 'frontend/exercises_catalog.html')

    def test_workouts_GET(self):
        response = self.client.get(self.workouts_url)

        self.assertIsNotNone(response.context['workouts'])  # verify if context is not None
        self.assertEqual(response.status_code, 200)         # verify status_code
        self.assertTemplateUsed(response, 'frontend/workouts_history.html')

    def test_stats_GET(self):
        response = self.client.get(self.stats_url)

        self.assertEqual(response.status_code, 200)
        self.assertTemplateUsed(response, 'frontend/workouts_stats.html')

    def test_add_exercise_GET(self):
        response = self.client.get(self.add_exercise_url)
            
        self.assertEqual(response.status_code, 200)                         # undefinedTable 'modules' not exist
        self.assertTemplateUsed(response, 'frontend/exercise_add.html')

    def test_add_exercise_POST(self):

        response = self.client.post(self.add_exercise_url, {
            'exercise_name': 'exercise test 1',
            'module': 1,
            'lesson_datetime': '01-01-2021 10:00',
            'lesson_tempo': 70,
            'img_path': '/exercises_img/test/100/',
            'note': 'notatka testowa',
            'how_many_img': 1
        })

        self.assertEquals(response.status_code, 302) # undefinedTable 'exercises' not exist
        

First 3 tests run ok, but 'test_add_exercise_GET' and 'test_add_exercise_POST' throws errors.

Traceback (most recent call last):
  File "C:\Users\Andrzej\PycharmProjects\DrummingPractice\drummingpractice\frontend\tests\test_views.py", line 69, in test_add_exercise_POST
    'how_many_img': 1
  File "C:\Users\Andrzej\PycharmProjects\DrummingPractice\venv\lib\site-packages\django\test\client.py", line 751, in post
    response = super().post(path, data=data, content_type=content_type, secure=secure, **extra)
  File "C:\Users\Andrzej\PycharmProjects\DrummingPractice\venv\lib\site-packages\django\test\client.py", line 408, in post
    secure=secure, **extra)
  File "C:\Users\Andrzej\PycharmProjects\DrummingPractice\venv\lib\site-packages\django\test\client.py", line 473, in generic
    return self.request(**r)
  File "C:\Users\Andrzej\PycharmProjects\DrummingPractice\venv\lib\site-packages\django\test\client.py", line 719, in request
    self.check_exception(response)
  File "C:\Users\Andrzej\PycharmProjects\DrummingPractice\venv\lib\site-packages\django\test\client.py", line 580, in check_exception
    raise exc_value
  File "C:\Users\Andrzej\PycharmProjects\DrummingPractice\venv\lib\site-packages\django\core\handlers\exception.py", line 47, in inner
    response = get_response(request)
  File "C:\Users\Andrzej\PycharmProjects\DrummingPractice\venv\lib\site-packages\django\core\handlers\base.py", line 181, in _get_response
    response = wrapped_callback(request, *callback_args, **callback_kwargs)
  File "C:\Users\Andrzej\PycharmProjects\DrummingPractice\drummingpractice\frontend\views.py", line 32, in add_exercise
    next_exercise_id = Exercises.objects.values('exercise_id').order_by('-exercise_id')[0]['exercise_id'] + 1
  File "C:\Users\Andrzej\PycharmProjects\DrummingPractice\venv\lib\site-packages\django\db\models\query.py", line 317, in __getitem__
    qs._fetch_all()
  File "C:\Users\Andrzej\PycharmProjects\DrummingPractice\venv\lib\site-packages\django\db\models\query.py", line 1324, in _fetch_all
    self._result_cache = list(self._iterable_class(self))
  File "C:\Users\Andrzej\PycharmProjects\DrummingPractice\venv\lib\site-packages\django\db\models\query.py", line 109, in __iter__
    for row in compiler.results_iter(chunked_fetch=self.chunked_fetch, chunk_size=self.chunk_size):
  File "C:\Users\Andrzej\PycharmProjects\DrummingPractice\venv\lib\site-packages\django\db\models\sql\compiler.py", line 1124, in results_iter
    results = self.execute_sql(MULTI, chunked_fetch=chunked_fetch, chunk_size=chunk_size)
  File "C:\Users\Andrzej\PycharmProjects\DrummingPractice\venv\lib\site-packages\django\db\models\sql\compiler.py", line 1169, in execute_sql
    cursor.execute(sql, params)
  File "C:\Users\Andrzej\PycharmProjects\DrummingPractice\venv\lib\site-packages\django\db\backends\utils.py", line 66, in execute
    return self._execute_with_wrappers(sql, params, many=False, executor=self._execute)
  File "C:\Users\Andrzej\PycharmProjects\DrummingPractice\venv\lib\site-packages\django\db\backends\utils.py", line 75, in _execute_with_wrappers
    return executor(sql, params, many, context)
  File "C:\Users\Andrzej\PycharmProjects\DrummingPractice\venv\lib\site-packages\django\db\backends\utils.py", line 84, in _execute
    return self.cursor.execute(sql, params)
  File "C:\Users\Andrzej\PycharmProjects\DrummingPractice\venv\lib\site-packages\django\db\utils.py", line 90, in __exit__
    raise dj_exc_value.with_traceback(traceback) from exc_value
  File "C:\Users\Andrzej\PycharmProjects\DrummingPractice\venv\lib\site-packages\django\db\backends\utils.py", line 84, in _execute
    return self.cursor.execute(sql, params)
django.db.utils.ProgrammingError: BŁĄD:  relation "exercises" does not exist
LINE 1: SELECT "exercises"."exercise_id" FROM "exercises" ORDER BY "...
                                              ^

I think the problem is with my models, because I using models from 'api' in 'frontend' app. I tried solutions from SO with 'makemigrations' and 'migrate', but I get 'no changes detected'. I tried also reset migrations from api and generate from 0, but still the same.

Anybody have idea what's going wrong? If architecture with models from different app is okay?

EDIT

models.py (api app)

from django.db import models

class Exercises(models.Model):
    exercise_id = models.AutoField(primary_key=True)
    exercise_name = models.CharField(max_length=500, blank=True, null=True)
    module = models.ForeignKey('Modules', models.DO_NOTHING, blank=True, null=True)
    lesson_datetime = models.DateTimeField(blank=True, null=True)
    lesson_tempo = models.IntegerField(blank=True, null=True)
    img_path = models.CharField(max_length=500, blank=True, null=True)
    note = models.CharField(max_length=500, blank=True, null=True)
    how_many_img = models.IntegerField(blank=True, null=True)

    class Meta:
        managed = False
        db_table = 'exercises'


class Modules(models.Model):
    module_id = models.AutoField(primary_key=True)
    module_name = models.CharField(max_length=500, blank=True, null=True)
    note = models.CharField(max_length=500, blank=True, null=True)

    class Meta:
        managed = False
        db_table = 'modules'


class Workouts(models.Model):
    workout_id = models.AutoField(primary_key=True)
    exercise = models.ForeignKey(Exercises, models.DO_NOTHING, blank=True, null=True)
    workout_datetime_start = models.DateTimeField(blank=True, null=True)
    workout_datetime_end = models.DateTimeField(blank=True, null=True)
    workout_tempo = models.IntegerField(blank=True, null=True)
    video_path = models.CharField(max_length=500, blank=True, null=True)
    note = models.CharField(max_length=500, blank=True, null=True)

    class Meta:
        managed = False
        db_table = 'workouts'

models.py (frontend app) is empty

My tables in postgresql are (skipping django tables):

  • modules
  • exercises
  • workouts

Names are correctly, lower case.

As I could see, the test with error is test_add_exercise_POST , and it's because you start with an empty database in test enviroment, you can't do Exercises.objects.values('exercise_id').order_by('-exercise_id')[0]['exercise_id'] + 1 inside add_exercise function, before creating test exercises objects and saving on test database.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM