You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Django REST Framework APITestCase无法创建ElephantSQL测试数据库

Django REST Framework测试数据库权限问题排查

我正在学习Python/Django REST Framework的测试方法,已经成功连接ElephantSQL免费版(tiny turtle)数据库并创建数据表,但使用APITestCase测试注册视图时遇到权限问题。

测试代码

import json
from django.contrib.auth.models import User
from django.urls import reverse
from rest_framework.authtoken.models import Token
from rest_framework.test import APITestCase
from rest_framework import status
from users.serializers.common import RegistrationSerializer, UserSerializer

class RegistrationTestCase(APITestCase):

  def test_registration(self):
    data = {'username': 'testuser', 'email': 'test@email.com', 'password': 'super_unique_password', 'password_confirmation': 'super_unique_password'}
    # Add a test user to database
    response = self.client.post('/api/auth/register/', data)
    # Test that 201 status is receieved
    self.assertEqual(response.status_code, status.HTTP_201_CREATED)

settings.py数据库配置

DATABASES = {
    'default': {
        'ENGINE': 'django.db.backends.postgresql_psycopg2',
        'NAME': env('DATABASE_NAME'),
        'HOST': env('DATABASE_HOST'),
        'PORT': 5432,
            'USER': env('DATABASE_USER'),
            'PASSWORD': env('DATABASE_PASS'),
    },
    'test': {
        'ENGINE': 'django.db.backends.postgresql_psycopg2',
        'NAME': env('DATABASE_NAME'),
        'HOST': env('DATABASE_HOST'),
        'PORT': 5432,
            'USER': env('DATABASE_USER'),
            'PASSWORD': env('DATABASE_PASS'),
    }
}

测试执行错误信息

执行命令 python manage.py test --verbosity=2 后报错:

Found 1 test(s).
Skipping setup of unused database(s): test.
Creating test database for alias 'default' ('test_<database_name_here>')...
/home/ben_kelly/.local/share/virtualenvs/Siege_of_the_Citadel_Companion-eBaHHEGM/lib/python3.10/site-packages/django/db/backends/postgresql/base.py:407: RuntimeWarning: Normally Django will use a connection to the 'postgres' database to avoid running initialization queries against the production database when it's not needed (for example, when running tests). Django was unable to create a connection to the 'postgres' database and will use the first PostgreSQL database instead.
  warnings.warn(
Got an error creating the test database: permission denied to create database

疑问

  • 如何排查是哪个用户触发了权限不足的问题?是settings.py中配置的数据库用户,还是psql登录用户?已确认psql用户为超级用户且拥有CREATEDB权限。
  • 移除settings中的test数据库配置后仍报错,且自定义的test数据库未被使用,如何强制APITestCase使用test数据库?
  • 添加的测试数据库别名打印代码未执行,请求相关帮助。

问题分析与解决步骤

1. 权限问题的触发用户排查

Django执行测试时,使用的是settings.py中配置的DATABASE_USER对应的远程数据库用户,和本地psql登录用户无关。ElephantSQL免费版(tiny turtle)默认不提供创建数据库的权限,即便本地用户是超级用户,远程用户的权限限制才是报错核心。

验证方式:直接用ElephantSQL提供的用户登录远程数据库,执行 CREATE DATABASE test_db;,会直接返回permission denied to create database,确认权限限制。

2. 强制使用自定义test数据库的方法

Django默认会自动创建test_<原数据库名>的测试库,但ElephantSQL不支持创建新库,需要修改配置让测试复用现有数据库(注意:测试会清空数据,建议提前备份):

修改settings.py:

DATABASES = {
    'default': {
        'ENGINE': 'django.db.backends.postgresql_psycopg2',
        'NAME': env('DATABASE_NAME'),
        'HOST': env('DATABASE_HOST'),
        'PORT': 5432,
        'USER': env('DATABASE_USER'),
        'PASSWORD': env('DATABASE_PASS'),
    }
}

# 测试环境配置,复用现有数据库
import sys
if 'test' in sys.argv:
    DATABASES['default']['TEST'] = {
        'NAME': env('DATABASE_NAME'),
        'MIGRATE': True,
    }

如果要强制使用之前配置的test数据库别名,需要在测试类中指定:

class RegistrationTestCase(APITestCase):
    databases = ['test']  # 指定使用test别名的数据库
    
    def test_registration(self):
        # 测试代码...

但注意:ElephantSQL免费版无法创建新库,test别名指向的是和默认库同名的远程库,本质还是同一个数据库,不如直接复用默认库更简单。

3. 测试数据库别名打印代码未执行的解决

如果打印代码没执行,排查两点:

  • 代码位置错误:要把打印代码放在测试类的setUp方法或测试方法中,比如:
class RegistrationTestCase(APITestCase):
    def setUp(self):
        from django.db import connections
        print("当前使用的数据库别名:", connections.databases)
  • 测试文件命名不符合规范:Django只会自动发现以test_开头的测试文件(比如test_registration.py),如果文件名不对,测试不会被执行。

额外建议

ElephantSQL免费版限制较多,不适合作为测试环境,建议:

  • 本地安装PostgreSQL作为测试数据库
  • 或在测试环境切换为SQLite,避免远程权限限制:
import sys
if 'test' in sys.argv:
    DATABASES['default'] = {
        'ENGINE': 'django.db.backends.sqlite3',
        'NAME': 'test_db.sqlite3',
    }

内容的提问来源于stack exchange,提问作者Phaliaetus

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.29 01:07:41