Ошибка тестового приложения django - ошибка при создании тестовой базы данных: в создании базы данных отказано


181

Когда я пытаюсь протестировать любое приложение с помощью команды (я заметил это, когда попытался развернуть myproject с помощью Fabric, которая использует эту команду):

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.
    }
}

Ответы:


373

Когда Django запускает набор тестов, в вашем случае он создает новую базу данных test_finance. Пользователь postgres с именем пользователя djangoне имеет разрешения на создание базы данных, поэтому появляется сообщение об ошибке.

Когда вы запускаете migrateили syncdb, Django не пытается создать financeбазу данных, поэтому вы не получите никаких ошибок.

Вы можете добавить разрешение созданного пользователя django, выполнив следующую команду в оболочке postgres как суперпользователь (подсказка к этому ответу о переполнении стека ).

=> ALTER USER django CREATEDB;

Примечание: имя пользователя, используемое в ALTER USER <username> CREATEDB;команде, должно соответствовать пользователю базы данных в ваших файлах настроек Django. В этом случае, оригинальный постер, был пользователь как djangoответ выше.


2
Хотя OP использовал postgresql, если вы используете mysql, у вас будет та же ошибка. Вы можете исправить это для mysql с помощью: => GRANT ALL ON *. * TO django @ localhost; Первоначально я пытался только GRANT CREATE ... но затем не мог выбрать или удалить созданную базу данных. По сути, это делает вашего пользователя суперпользователем, поэтому будьте осторожны.
mightypile

1
Я немного поэкспериментировал и обнаружил, что минимальные глобальные привилегии: - Данные: SELECT, INSERT, UPDATE, DELETE, Структура: CREATE, ALTER, INDEX, DROP, Admin: REFERENCES. Не супер-пользователь, но все же довольно мощный, так что будьте осторожны.
Скотт

для моего случая я предоставляю все права на тестовую базу данных, что-то вроде этого:GRANT ALL PRIVILEGES ON test_my_db.* TO 'my_user'@'localhost';
Yacine Rouizi

17

Я нашел интересное решение вашей проблемы.
Фактически для 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',
        },
    }
}

запустить оболочку MySQL от имени пользователя root:

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 в качестве СУБД. К чему будет относиться projectname_test ?
код-кобольд

@ code-kobold 7, Да, но я тоже вижу ту же ошибку в mysql. Значение имя_проекта_test относится к названию проекта, в моем ответе это myproject.
Чандан

2

В моем случае решения GRANT PRIVILEGES не работали с Python 3.7.2 , Django 2.1.7 и MySQL 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

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"

0

Ничего себе, комбинируя все ответы здесь с небольшой настройкой, наконец, я получил рабочее решение для docker-compose, django и postgres ...

Во-первых, команда postgres, заданная noufal valapra, неверна (или, возможно, просто не актуальна), она должна быть:

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;

Тогда Dockerfile для postgres выглядит так:

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:

0

Может быть, вы поставили свой тест в режиме ожидания или в качестве фоновой работы. Попробуйте с fgкомандой в Bash Shell.


0

Аккаунт суперпользователя - это самый простой способ гарантировать беспроблемное тестирование. так что более простой способ сделать djangoпользователя su - это сделать ALTER django WITH SUPERUSER.

для получения дополнительной информации https://www.postgresql.org/docs/current/sql-alteruser.html

Используя наш сайт, вы подтверждаете, что прочитали и поняли нашу Политику в отношении файлов cookie и Политику конфиденциальности.
Licensed under cc by-sa 3.0 with attribution required.