web-dev-qa-db-fra.com

django erreur de l'application de test - Vous rencontrez une erreur lors de la création de la base de données de test: permission refusée pour créer la base de données

Lorsque j'essaie de tester une application avec une commande (je l'ai remarquée lorsque j'ai essayé de déployer mon projet à l'aide de fabric, qui utilise cette commande):

python manage.py test appname

Je reçois cette erreur:

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

La commande syncdb semble fonctionner. Les paramètres de ma base de données dans 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.
    }
}
152
Andrius

Lorsque Django exécute la suite de tests, il crée une nouvelle base de données, dans votre cas test_finance. L'utilisateur postgres avec le nom d'utilisateur Django n'a pas l'autorisation de créer une base de données, d'où le message d'erreur.

Lorsque vous exécutez migrate ou syncdb, Django ne tente pas de créer la base de données finance, vous ne recevrez donc aucune erreur.

Vous pouvez ajouter l’autorisation createdb à l’utilisateur Django) en exécutant la commande suivante dans le shell postgres en tant que super-utilisateur (astuce chapeau à réponse de débordement de pile ).

=> ALTER USER Django CREATEDB;

Remarque: Le nom d'utilisateur utilisé dans le ALTER USER <username> CREATEDB; La commande doit correspondre à l’utilisateur de la base de données dans vos Django fichiers de paramètres. Dans ce cas, l’affiche originale avait pour utilisateur Django la réponse ci-dessus.

319
Alasdair

J'ai trouvé une solution intéressante à votre problème.
En fait, pour MySQL, vous pouvez accorder des privilèges à une base de données inexistante.
Vous pouvez donc ajouter le nom 'test_finance' pour votre base de données de tests dans vos paramètres:

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

démarrez MySQL Shell en tant qu'utilisateur root:

mysql -u root -p

et maintenant, accordez tous les privilèges à cette base de données non existante dans MySQL:

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

Maintenant Django lancera les tests sans aucun problème.

13
Yurii Halapup

Dans le cas de Postgres, l'utilisateur doit avoir l'autorisation createdb.

ALTER ROLE miriam CREATEDB;

Voir cette documentation: https://docs.djangoproject.com/fr/2.0/topics/testing/overview/#the-test-database

4
Noufal Valapra

Si la base de données est mysql, alors ces deux modifications vont faire avancer les choses.

1.Ouvre mysite/mysite/settings.py

Les paramètres de votre base de données doivent avoir un bloc TEST supplémentaire, comme indiqué avec nom_projet_test.

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

2. Tapez la commande ci-dessous en utilisant invite mysql ou mysql workbench pour donner tous les privilèges à l'utilisateur spécifié dans settings.py

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

Maintenant vous pouvez courir python manage.py test polls.

3
Chandan

Dans mon cas, les solutions GRANT PRIVILEGES ne fonctionnaient pas avec Python 3.7.2, Django 2.1.7 et MySQL 5.6.2 ... Je ne sais pas pourquoi.

J'ai donc décidé d'utiliser SQLite comme base de données 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'),
        },
    }
}

Après cela, la voiture TESTS fonctionne sans problème:

$ 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
JavierFuentes

Wow, alors combiner toutes les réponses ici avec un peu de peaufinage m'a enfin conduit à une solution de travail pour docker-compose, Django et postgres ...

Tout d’abord, la commande postgres donnée par noufal valapra n’est pas correcte (ou peut-être simplement non actuelle), elle devrait être:

ALTER USER docker WITH CREATEDB;

Dans le cas d'une configuration docker-compose, cela ira dans le fichier init.sql, voici à quoi ressemble le mien:

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

Ensuite, le fichier Dockerfile pour postgres ressemble à ceci:

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

Ensuite, le Django settings.py a cette entrée:

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

et le docker-compose ressemble à ceci:

version: '3.6'

prestations de service:

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
Paul Jacobs

Si vous utilisez docker-compose ce qui a fonctionné pour moi a été le suivant:

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

ou

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

Mes paramètres ressemblent à ceci:

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

et mon docker-compose.yml se présente comme suit:

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
lmiguelvargasf