Error de la aplicación de prueba de django: error al crear la base de datos de prueba: permiso denegado para crear la base de datos

181

Cuando trato de probar cualquier aplicación con comando (lo noté cuando traté de implementar mi proyecto usando fabric, que usa este comando):

python manage.py test appname

Me sale este 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

syncdbEl comando parece funcionar. La configuración de mi base de datos en 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
fuente

Respuestas:

373

Cuando Django ejecuta el conjunto de pruebas, crea una nueva base de datos, en su caso test_finance. El usuario postgres con nombre de usuario djangono tiene permiso para crear una base de datos, de ahí el mensaje de error.

Cuando ejecuta migrateo syncdb, Django no intenta crear la financebase de datos, por lo que no obtiene ningún error.

Puede agregar el permiso createdb al usuario de django ejecutando el siguiente comando en el shell de postgres como superusuario (punta de sombrero para esta respuesta de desbordamiento de pila ).

=> ALTER USER django CREATEDB;

Nota: El nombre de usuario utilizado en el ALTER USER <username> CREATEDB;comando debe coincidir con el usuario de la base de datos en sus archivos de configuración de Django. En este caso, el póster original tenía al usuario como djangola respuesta anterior.

Alasdair
fuente
2
Aunque el OP usó postgresql, si está usando mysql tendrá el mismo error. Puede arreglarlo para mysql con: => OTORGAR TODO ENCENDIDO *. * A django @ localhost; Originalmente intenté GRANT CREATE ... pero luego no pude SELECCIONAR o COLOCAR la base de datos creada. Básicamente, esto hace que su usuario sea un superusuario, así que tenga cuidado.
mightypile
1
Experimenté un poco y descubrí que los privilegios globales mínimos son: Datos: SELECCIONAR, INSERTAR, ACTUALIZAR, ELIMINAR, Estructura: CREAR, ALTERAR, ÍNDICE, BAJAR, Admin: REFERENCIAS. No es un superusuario, pero sigue siendo bastante poderoso, así que tenga cuidado.
Scott
para mi caso, otorgo todos los privilegios a la base de datos de prueba, algo como esto:GRANT ALL PRIVILEGES ON test_my_db.* TO 'my_user'@'localhost';
Yacine Rouizi
17

He encontrado una solución interesante a tu problema.
De hecho, para MySQL puede otorgar privilegios para bases de datos no existentes.
Por lo tanto, puede agregar el nombre 'test_finance' para su base de datos de prueba en su configuración:

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

Inicie MySQL Shell como usuario root:

mysql -u root -p

y ahora otorgue todos los privilegios a esta base de datos no existente en MySQL:

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

Ahora Django comenzará las pruebas sin ningún problema.

Yurii Halapup
fuente
4

Si la base de datos es mysql , estos dos cambios harán las cosas.

1.Abra mysite / mysite / settings.py

La configuración de su base de datos debe tener un bloque TEST adicional como se muestra con projectname_test .

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

2. Escriba el comando a continuación utilizando el símbolo del sistema mysql o mysql workbench para dar todos los privilegios al usuario especificado en settings.py

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

Ahora puedes correr python manage.py test polls.

Chandan
fuente
La pregunta obviamente usa Postgres como DBMS. ¿Con qué se relacionaría projectname_test ?
code-kobold
@ code-kobold 7, Sí, pero también puedo ver el mismo error en mysql. El valor projectname_test se refiere al nombre del proyecto, por ejemplo, en mi respuesta es myproject.
Chandan
1

Si está utilizando docker-composelo que funcionó para mí fue lo siguiente:

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

o

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

Mi configuración se ve así:

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

y mi docker-compose.ymlaspecto de la siguiente manera:

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
fuente
1

En mi caso, las soluciones GRANT PRIVILEGES no funcionaron con Python 3.7.2 , Django 2.1.7 y MySQL 5.6.23 ... No sé por qué.

Entonces decidí usar SQLite como base de datos 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'),
        },
    }
}

Después de eso, el auto TESTS corre sin problemas:

$ 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
fuente
0

Wow, así que combinar todas las respuestas aquí con un pequeño ajuste finalmente me llevó a una solución de trabajo para docker-compose, django y postgres ...

Primero, el comando postgres dado por noufal valapra no es correcto (o tal vez simplemente no es actual), debería ser:

ALTER USER docker WITH CREATEDB;

En el caso de una configuración docker-compose, esto irá en el archivo init.sql, así es como se ve el mío:

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

Entonces el Dockerfile para postgres se ve así:

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

Entonces el Django settings.py tiene esta entrada:

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

y el docker-compose se ve así:

versión: '3.6'

servicios:

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
fuente
0

Tal vez pones tu prueba en modo suspendido o como un trabajo en segundo plano. Intente con el fgcomando en bash shell.

eEmanuel Oviedo
fuente