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

当我尝试使用命令测试任何应用程序时(当我尝试使用使用此命令的结构来部署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.
    }
}

When I try to test any app with command (I noticed it when I tried to deploy myproject using fabric, which uses this command):

python manage.py test appname

I get this error:

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 command seems to work. My database settings in 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.
    }
}

回答 0

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

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

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

=> ALTER USER django CREATEDB;

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

When Django runs the test suite, it creates a new database, in your case test_finance. The postgres user with username django does not have permission to create a database, hence the error message.

When you run migrate or syncdb, Django does not try to create the finance database, so you don’t get any errors.

You can add the createdb permission to the django user by running the following command in the postgres shell as a superuser (hat tip to this stack overflow answer).

=> ALTER USER django CREATEDB;

Note: The username used in the ALTER USER <username> CREATEDB; command needs to match the database user in your Django settings files. In this case, the original poster, had the user as django the above answer.


回答 1

我找到了解决您问题的有趣方法。
实际上,对于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将毫无问题地开始测试。

I have found interesting solution to your problem.
In fact for MySQL you can grant privileges for non-existing database.
So you can add name ‘test_finance’ for your test database in your settings:

    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',
        },
    }
}

start MySQL shell as the root user:

mysql -u root -p

and now grant all privileges to this non-existing database in MySQL:

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

Now Django will start tests without any problems.


回答 2

对于Postgres,用户必须具有createdb权限。

ALTER ROLE miriam CREATEDB;

请参阅此文档:https : //docs.djangoproject.com/zh-CN/2.0/topics/testing/overview/#the-test-database

In the case of Postgres, the user must have createdb permission.

ALTER ROLE miriam CREATEDB;

See this documentation: https://docs.djangoproject.com/en/2.0/topics/testing/overview/#the-test-database


回答 3

如果数据库是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

If database is mysql then these two changes will get the things done.

1.Open mysite/mysite/settings.py

Your database settings should have an additional TEST block as shown with projectname_test.

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

2.Type the below command using mysql command prompt or mysql workbench to give all privilages to the user specified in settings.py

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

Now you can run python manage.py test polls.


回答 4

如果您使用的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"

If you are using docker-compose what worked for me was the following:

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

or

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

My settings looks like this:

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

and my docker-compose.yml looks as follows:

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"

回答 5

就我而言,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

In my case, GRANT PRIVILEGES solutions didn’t work with Python 3.7.2, Django 2.1.7 and MySQL 5.6.23… I don’t know why.

So I decided to use SQLite as a TEST database…

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'),
        },
    }
}

After that, TESTS car run without troubles:

$ 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

回答 6

哇,所以结合这里的所有答案和一点点调整,终于使我得到了一个适用于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:

Wow so combining all of the answers here with a little tweaking finally got me to a working solution for docker-compose, django, and postgres…

First the postgres command given by noufal valapra is not correct (or maybe just not current), it should be:

ALTER USER docker WITH CREATEDB;

In the case of a docker-compose setup, this will go in the init.sql file, this is what mine looks like:

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

Then the Dockerfile for postgres looks like this:

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

Then the Django settings.py has this entry:

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'],
        }
    }

and the docker-compose looks like this:

version: ‘3.6’

services:

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:

回答 7

也许您将测试置于暂停模式或作为后台工作。尝试fg在bash shell中使用命令。

Maybe you put your test in suspended mode or as a backgrounded job. Try with fg command in bash shell.


回答 8

超级用户帐户是保证测试顺利的最简单方法。因此,使django用户su 更简单的方法就是这样做ALTER django WITH SUPERUSER

有关更多信息https://www.postgresql.org/docs/current/sql-alteruser.html

A superuser account is the easiest way to guarantee smooth testing. so a simpler way of making the django user su is to do ALTER django WITH SUPERUSER .

for more information https://www.postgresql.org/docs/current/sql-alteruser.html


声明:本站所有文章,如无特殊说明或标注,均为本站原创发布。任何个人或组织,在未征得本站同意时,禁止复制、盗用、采集、发布本站内容到任何网站、书籍等各类媒体平台。如若本站内容侵犯了原著者的合法权益,可联系我们进行处理。