django test app error - Errore nella creazione del database di test: autorizzazione negata per la creazione del database


181

Quando provo a testare qualsiasi app con comando (l'ho notato quando ho provato a distribuire myproject usando fabric, che utilizza questo comando):

python manage.py test appname

Ottengo questo errore:

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

syncdbil comando sembra funzionare. Le mie impostazioni del database in 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.
    }
}

Risposte:


373

Quando Django esegue la suite di test, crea un nuovo database, nel tuo caso test_finance. L'utente postgres con nome utentedjango non dispone dell'autorizzazione per creare un database, quindi il messaggio di errore.

Quando corri migrateo syncdb, Django non prova a creare il filefinance database, quindi non ricevi errori.

È possibile aggiungere l'autorizzazione createb all'utente django eseguendo il seguente comando nella shell postgres come superutente (hat hat a questa risposta di overflow dello stack ).

=> ALTER USER django CREATEDB;

Nota: il nome utente utilizzato nel ALTER USER <username> CREATEDB;comando deve corrispondere all'utente del database nei file delle impostazioni di Django. In questo caso, il poster originale aveva l'utente come djangorisposta sopra.


2
Sebbene l'OP abbia usato postgresql, se stai usando mysql avrai lo stesso errore. Puoi ripararlo per mysql con: => GRANT ALL ON *. * TO django @ localhost; Inizialmente ho provato a GRANT CREATE ... ma poi non sono riuscito a SELEZIONARE o GOCCIARE il database creato. Questo essenzialmente rende l'utente un superutente, quindi fai attenzione.
poderoso

1
Ho sperimentato un po 'e ho scoperto che i privilegi globali minimi sono: Dati: SELEZIONA, INSERISCI, AGGIORNA, ELIMINA, Struttura: CREA, ALTER, INDICE, GOCCIA, Amministratore: RIFERIMENTI. Non un superutente, ma comunque piuttosto potente, quindi fai attenzione.
Scott,

per il mio caso concedo tutti i privilegi al database di test, qualcosa del genere:GRANT ALL PRIVILEGES ON test_my_db.* TO 'my_user'@'localhost';
Yacine Rouizi

17

Ho trovato una soluzione interessante al tuo problema.
Infatti per MySQL è possibile concedere privilegi per database inesistenti.
Quindi puoi aggiungere il nome 'test_finance' per il tuo database di test nelle tue impostazioni:

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

avvia la shell MySQL come utente root:

mysql -u root -p

e ora concedi tutti i privilegi a questo database inesistente in MySQL:

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

Ora Django inizierà i test senza problemi.



4

Se il database è mysql, queste due modifiche porteranno a termine le cose.

1.Aprire mysite / mysite / settings.py

Le impostazioni del database devono avere un blocco TEST aggiuntivo, come mostrato 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. Digitare il comando seguente usando il prompt dei comandi mysql o mysql workbench per dare tutti i privilegi all'utente specificato in settings.py

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

Adesso puoi correre python manage.py test polls.


La domanda ovviamente utilizza Postgres come DBMS. A cosa si riferirebbe projectname_test ?
code-kobold,

@ code-kobold 7, Sì, ma posso vedere lo stesso errore anche in mysql. Il valore projectname_test è riferito al nome del progetto ex. nella mia risposta è myproject.
Chandan,

2

Nel mio caso, le soluzioni GRANT PRIVILEGES non funzionavano con Python 3.7.2 , Django 2.1.7 e MySQL 5.6.23 ... Non so perché.

Quindi ho deciso di utilizzare SQLite come database 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'),
        },
    }
}

Successivamente, l'auto TEST funziona senza problemi:

$ 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

Se stai usando docker-composeciò che ha funzionato per me è stato il seguente:

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

o

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

Le mie impostazioni si presentano così:

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

e il mio docker-compose.ymlaspetto è il seguente:

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

Wow, quindi combinando tutte le risposte qui con un piccolo ritocco finalmente mi ha portato a una soluzione funzionante per docker-compose, django e postgres ...

Innanzitutto il comando postgres dato da noufal valapra non è corretto (o forse non è attuale), dovrebbe essere:

ALTER USER docker WITH CREATEDB;

Nel caso di un'installazione composta da docker, questo andrà nel file init.sql, ecco come appare il mio:

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

Quindi il Dockerfile per Postgres è simile al seguente:

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

Quindi Django settings.py ha questa voce:

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

e il docker-compose assomiglia a questo:

versione: '3.6'

Servizi:

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

Forse hai messo il test in modalità sospesa o come processo in background. Prova con il fgcomando nella shell bash.


Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.