Erreur d'application de test django - Une erreur s'est produite lors de la création de la base de données de test: autorisation refusée pour créer la base de données

181

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

python manage.py test appname

J'obtiens 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

syncdbla commande semble fonctionner. Mes paramètres de 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.
    }
}
Andrius
la source

Réponses:

373

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 djangon'a pas l'autorisation de créer une base de données, d'où le message d'erreur.

Lorsque vous exécutez migrateou syncdb, Django n'essaye pas de créer la financebase de données, donc vous n'obtenez aucune erreur.

Vous pouvez ajouter l'autorisation createdb à l'utilisateur django en exécutant la commande suivante dans le shell postgres en tant que superutilisateur (pointe du chapeau à cette réponse de débordement de pile ).

=> ALTER USER django CREATEDB;

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

Alasdair
la source
2
Bien que l'OP ait utilisé postgresql, si vous utilisez mysql, vous aurez la même erreur. Vous pouvez le corriger pour mysql avec: => GRANT ALL ON *. * TO django @ localhost; J'ai d'abord essayé de GRANT CREATE ... mais ensuite je n'ai pas pu SELECT ou DROP la base de données créée. Cela fait essentiellement de votre utilisateur un super-utilisateur, alors soyez prudent.
mightypile
1
J'ai expérimenté un peu et j'ai trouvé que les privilèges globaux minimums sont - Données: SELECT, INSERT, UPDATE, DELETE, Structure: CREATE, ALTER, INDEX, DROP, Admin: REFERENCES. Pas un super-utilisateur, mais toujours assez puissant, alors soyez prudent.
Scott
pour mon cas j'accorde tous les privilèges pour tester la base de données, quelque chose comme ceci:GRANT ALL PRIVILEGES ON test_my_db.* TO 'my_user'@'localhost';
Yacine Rouizi
17

J'ai trouvé une solution intéressante à votre problème.
En fait, pour MySQL, vous pouvez accorder des privilèges pour une base de données non existante.
Vous pouvez donc ajouter le nom 'test_finance' pour votre base de données de test 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 le shell MySQL en tant qu'utilisateur root:

mysql -u root -p

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

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

Django va maintenant démarrer les tests sans aucun problème.

Yurii Halapup
la source
4

Si la base de données est mysql, ces deux changements feront les choses.

1.Ouvrez mysite / mysite / settings.py

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

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

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

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

Vous pouvez maintenant courir python manage.py test polls.

Chandan
la source
La question utilise évidemment Postgres comme SGBD. Quel serait le lien entre projectname_test ?
code-kobold
@ code-kobold 7, Oui, mais je peux également voir la même erreur dans mysql.La valeur projectname_test fait référence au nom du projet, par exemple dans ma réponse, c'est myproject.
Chandan
1

Si vous utilisez docker-composece qui a fonctionné pour moi, c'est ce qui suit:

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 mes docker-compose.ymlregards 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"
lmiguelvargasf
la source
1

Dans mon cas, les solutions GRANT PRIVILEGES ne fonctionnaient pas avec Python 3.7.2 , Django 2.1.7 et MySQL 5.6.23 ... 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èmes:

$ 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
JavierFuentes
la source
0

Wow, donc combiner toutes les réponses ici avec un petit ajustement m'a finalement permis de trouver une solution de travail pour docker-compose, django et postgres ...

Premièrement, la commande postgres donnée par noufal valapra n'est pas correcte (ou peut-être tout simplement pas 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 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:
Paul Jacobs
la source
0

Peut-être que vous mettez votre test en mode suspendu ou en tant que travail en arrière-plan. Essayez avec la fgcommande dans le shell bash.

eEmanuel Oviedo
la source