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