psycopg2.errors.UndefinedTable:关系“练习”不存在 - Django 测试
psycopg2.errors.UndefinedTable: relation “exercises” does not exist - Django Testing
我开始用 Django 编写我的第一个测试。我在测试基于模型的 POST 方法时遇到问题。
我的项目树看起来:
- 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
我正在为应用编写测试 'frontend'。我试过测试函数 '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)
我在前端应用程序中的 'test_views.py' 文件如下所示:
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
前 3 个测试 运行 正常,但是 'test_add_exercise_GET' 和 'test_add_exercise_POST' 会抛出错误。
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 "...
^
我认为问题出在我的模型上,因为我在 'frontend' 应用程序中使用了来自 'api' 的模型。我用 'makemigrations' 和 'migrate' 尝试了 SO 的解决方案,但我得到了 'no changes detected'。我也试过从 api 重置迁移并从 0 生成,但还是一样。
有人知道出了什么问题吗?来自不同应用程序的模型架构是否可以?
编辑
models.py(api 应用程序)
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(前端应用)为空
我在 postgresql 中的表是(跳过 django 表):
- 模块
- 练习
- 锻炼
名称正确,小写。
正如我所见,错误的测试是 test_add_exercise_POST
,这是因为你在测试环境中从一个空数据库开始,你不能在 add_exercise
中执行 Exercises.objects.values('exercise_id').order_by('-exercise_id')[0]['exercise_id'] + 1
函数,在创建测试练习对象并保存到测试数据库之前。
我开始用 Django 编写我的第一个测试。我在测试基于模型的 POST 方法时遇到问题。
我的项目树看起来:
- 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
我正在为应用编写测试 'frontend'。我试过测试函数 '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)
我在前端应用程序中的 'test_views.py' 文件如下所示:
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
前 3 个测试 运行 正常,但是 'test_add_exercise_GET' 和 'test_add_exercise_POST' 会抛出错误。
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 "...
^
我认为问题出在我的模型上,因为我在 'frontend' 应用程序中使用了来自 'api' 的模型。我用 'makemigrations' 和 'migrate' 尝试了 SO 的解决方案,但我得到了 'no changes detected'。我也试过从 api 重置迁移并从 0 生成,但还是一样。
有人知道出了什么问题吗?来自不同应用程序的模型架构是否可以?
编辑
models.py(api 应用程序)
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(前端应用)为空
我在 postgresql 中的表是(跳过 django 表):
- 模块
- 练习
- 锻炼
名称正确,小写。
正如我所见,错误的测试是 test_add_exercise_POST
,这是因为你在测试环境中从一个空数据库开始,你不能在 add_exercise
中执行 Exercises.objects.values('exercise_id').order_by('-exercise_id')[0]['exercise_id'] + 1
函数,在创建测试练习对象并保存到测试数据库之前。