django测试应用程序错误-创建测试数据库时出错:创建数据库的权限被拒绝


181

当我尝试使用命令测试任何应用程序时(当我尝试使用使用此命令的结构来部署myproject时,我注意到了它):

python manage.py test appname

我收到此错误:

Creating test database for alias 'default'...
Got an error creating the test database: permission denied to create database

Type 'yes' if you would like to try deleting the test database 'test_finance', or 'no' to cancel

syncdb命令似乎起作用。我在settings.py中的数据库设置:

DATABASES = {
    'default': {
        'ENGINE': 'django.db.backends.postgresql_psycopg2', # Add 'postgresql_psycopg2', 'mysql', 'sqlite3' or 'oracle'.
        'NAME': 'finance',                      # Or path to database file if using sqlite3.
        'USER': 'django',                      # Not used with sqlite3.
        'PASSWORD': 'mydb123',                  # Not used with sqlite3.
        'HOST': '127.0.0.1',                      # Set to empty string for localhost. Not used with sqlite3.
        'PORT': '',                      # Set to empty string for default. Not used with sqlite3.
    }
}

Answers:


370

Django运行测试套件时,在您的情况下,它将创建一个新数据库test_finance。具有用户名的postgres用户django无权创建数据库,因此出现错误消息。

当您运行migrate或时syncdb,Django不会尝试创建finance数据库,因此不会出现任何错误。

您可以通过以超级用户身份在postgres shell中运行以下命令来向django用户添加createdb权限(此堆栈溢出答案的提示)。

=> ALTER USER django CREATEDB;

注意:ALTER USER <username> CREATEDB;命令中使用的用户名需要与Django设置文件中的数据库用户匹配。在这种情况下,原始张贴者将用户作为django上述答案。


2
尽管OP使用了postgresql,但是如果您使用的是mysql,则会出现相同的错误。您可以使用以下命令为mysql修复它:=> GRANT ALL ON *。* TO django @ localhost; 我本来只尝试GRANT CREATE ...,但是之后却无法选择或删除创建的数据库。这实际上使您的用户成为超级用户,因此请当心。
mayypile 2015年

1
我做了一些实验,发现最小的全局特权是-数据:选择,插入,更新,删除,结构:创建,更改,索引,删除,管理:参考。不是超级用户,但仍然非常强大,因此请谨慎使用。
斯科特

就我而言,我授予所有特权以测试数据库,如下所示:GRANT ALL PRIVILEGES ON test_my_db.* TO 'my_user'@'localhost';
Yacine Rouizi

16

我找到了解决您问题的有趣方法。
实际上,对于MySQL,您可以授予不存在的数据库特权。
因此,您可以在设置中为测试数据库添加名称“ test_finance”:

    DATABASES = {
    'default': {
        'ENGINE': 'django.db.backends.postgresql_psycopg2', # Add 'postgresql_psycopg2', 'mysql', 'sqlite3' or 'oracle'.
        'NAME': 'finance',                      # Or path to database file if using sqlite3.
        'USER': 'django',                      # Not used with sqlite3.
        'PASSWORD': 'mydb123',                  # Not used with sqlite3.
        'HOST': '127.0.0.1',                      # Set to empty string for localhost. Not used with sqlite3.
        'PORT': '',                      # Set to empty string for default. Not used with sqlite3.
        'TEST': {
            'NAME': 'test_finance',
        },
    }
}

以root用户身份启动MySQL Shell:

mysql -u root -p

现在将所有特权授予该MySQL中不存在的数据库:

GRANT ALL PRIVILEGES ON test_finance.* TO 'django'@'localhost';

现在,Django将毫无问题地开始测试。



4

如果数据库是mysql,那么这两个更改将完成任务。

1.打开mysite / mysite / settings.py

您的数据库设置应具有一个额外的TEST块,如projectname_test所示。

DATABASES = {
    'default': {
        'ENGINE': 'django.db.backends.mysql',
        'NAME': 'myproject',
        'USER': 'chandan',
        'PASSWORD': 'root',
        'HOST': 'localhost',
        'PORT': '3306',
        'TEST': {
            'NAME': 'myproject_test',
        },
    }
}

2.使用mysql命令提示符mysql工作台键入以下命令,将所有特权授予settings.py中指定的用户

GRANT ALL PRIVILEGES ON myproject_test.* TO 'chandan'@'localhost';

现在您可以运行 python manage.py test polls


这个问题显然使用Postgres作为DBMS。projectname_test与什么有关?
code-kobold

@ code-kobold 7,是的,但是我也可以在mysql中看到相同的错误。值projectname_test指的是项目ex。的名称,我的答案是myproject。
Chandan

1

如果您使用的docker-compose是对我有用的,则如下:

ALTER ROLE username CREATEDB;
GRANT ALL PRIVILEGES ON test_database_name.* TO 'username';

要么

ALTER ROLE username CREATEDB;
GRANT ALL PRIVILEGES ON *.* TO 'username'@'%';

我的设置如下所示:

DATABASES = {
    'default': {
        'ENGINE': 'django.db.backends.mysql',
        'NAME': 'database_name',
        'USER': 'username',
        'PASSWORD': 'password',
        'HOST': 'db',
        'PORT': '3306',
    }
}

和我的docker-compose.yml样子如下:

version: '3'
services:
  web:
      build: .
      command: './wait_for_db_and_start_server.sh'
      env_file: env_web
      working_dir: /project_name
      links:
        - db
      volumes:
        - .:/volume_name
      ports:
        - "8000:8000"
      depends_on:
        - db
  db:
    image: mysql:5.7
    restart: always
    env_file: env_db
    working_dir: /db
    volumes:
      - ./Dump.sql:/db/Dump.sql
    ports:
      - "3306:3306"

1

就我而言,GRANT PRIVILEGES解决方案不适用于Python 3.7.2Django 2.1.7MySQL 5.6.23 ...我不知道为什么。

所以我决定使用SQLite作为TEST数据库...

DATABASES = {
    'default': {
        'NAME': 'productiondb',
        'ENGINE': 'mysql.connector.django',   # 'django.db.backends.mysql'
        'USER': '<user>',
        'PASSWORD': '<pass>',
        'HOST': 'localhost',
        'PORT': 3306,
        'OPTIONS': {
            'autocommit': True,
        },
        'TEST': {
            'ENGINE': 'django.db.backends.sqlite3',
            'NAME': os.path.join(BASE_DIR, 'db.sqlite3'),
        },
    }
}

此后,TESTS的汽车运行就没有麻烦了:

$ python manage.py test
Creating test database for alias 'default'...
System check identified no issues (0 silenced).

Destroying test database for alias 'default'...
----------------------------------------------------------------------
Ran 0 tests in 0.000s

OK

Process finished with exit code 0

0

哇,所以结合这里的所有答案和一点点调整,终于使我得到了一个适用于docker-compose,django和postgres的有效解决方案...

首先,noufal valapra给出的postgres命令不正确(或者可能不是最新的),它应该是:

ALTER USER docker WITH CREATEDB;

如果是docker-compose设置,它将进入init.sql文件,这就是我的样子:

CREATE USER docker;
ALTER USER docker WITH CREATEDB;
CREATE DATABASE djangodb;
GRANT ALL PRIVILEGES ON DATABASE djangodb TO docker;

然后用于postgres的Dockerfile如下所示:

FROM postgres:10.1-alpine
COPY init.sql /docker-entrypoint-initdb.d/

然后Django settings.py具有以下条目:

if 'RDS_DB_NAME' in os.environ:
    INTERNAL_DATABASES = {
        'default': {
            'ENGINE': 'django.db.backends.postgresql_psycopg2',
            'NAME': os.environ['RDS_DB_NAME'],
            'USER': os.environ['RDS_USERNAME'],
            'PASSWORD': os.environ['RDS_PASSWORD'],
            'HOST': os.environ['RDS_HOSTNAME'],
            'PORT': os.environ['RDS_PORT'],
        }
    }

和docker-compose看起来像这样:

版本:“ 3.6”

服务:

postgresdb:
  build:
    context: ./
    dockerfile: ./Dockerfile-postgresdb
  volumes:
    - postgresdata:/var/lib/postgresql/data/

django:
  build:
    context: ../
    dockerfile: ./docker/Dockerfile
  environment:
    - RDS_DB_NAME=djangodb
    - RDS_USERNAME=docker
    - RDS_PASSWORD=docker
    - RDS_HOSTNAME=postgresdb
    - RDS_PORT=5432

  stdin_open: true
  tty: true
  depends_on:
    - postgresdb

volumes:
    postgresdata:


By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.