django test app error - Beim Erstellen der Testdatenbank ist ein Fehler aufgetreten: Berechtigung zum Erstellen der Datenbank verweigert

180

Wenn ich versuche, eine App mit einem Befehl zu testen (ich habe es bemerkt, als ich versucht habe, mein Projekt mithilfe von Fabric bereitzustellen, das diesen Befehl verwendet):

python manage.py test appname

Ich bekomme diesen Fehler:

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

syncdbBefehl scheint zu funktionieren. Meine Datenbankeinstellungen 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.
    }
}
Andrius
quelle

Antworten:

369

Wenn Django die Testsuite ausführt, wird in Ihrem Fall eine neue Datenbank erstellt test_finance. Der Benutzer von postgres mit Benutzername djangohat keine Berechtigung zum Erstellen einer Datenbank, daher die Fehlermeldung.

Wenn Sie migrateoder ausführen syncdb, versucht Django nicht, die financeDatenbank zu erstellen , sodass keine Fehler angezeigt werden.

Sie können dem Benutzer django die Berechtigung createdb hinzufügen, indem Sie den folgenden Befehl in der Postgres-Shell als Superuser ausführen (Tipp für diese Stapelüberlaufantwort ).

=> ALTER USER django CREATEDB;

Hinweis: Der im ALTER USER <username> CREATEDB;Befehl verwendete Benutzername muss mit dem Datenbankbenutzer in Ihren Django-Einstellungsdateien übereinstimmen. In diesem Fall hatte das Originalposter den Benutzer als djangoobige Antwort.

Alasdair
quelle
2
Obwohl das OP postgresql verwendet hat, wird bei Verwendung von mysql der gleiche Fehler angezeigt. Sie können es für MySQL beheben mit: => GRANT ALL ON *. * TO django @ localhost; Ich habe ursprünglich versucht, nur CREATE ZU GEWÄHREN ... konnte dann aber die erstellte Datenbank nicht SELECT oder DROP. Dies macht Ihren Benutzer im Wesentlichen zu einem Superuser. Seien Sie also vorsichtig.
Mightypile
1
Ich habe ein wenig experimentiert und festgestellt, dass die globalen Mindestprivilegien - Daten: SELECT, INSERT, UPDATE, DELETE, Struktur: CREATE, ALTER, INDEX, DROP, Admin: REFERENCES sind. Kein Superuser, aber dennoch ziemlich mächtig. Seien Sie also vorsichtig.
Scott
Für meinen Fall GRANT ALL PRIVILEGES ON test_my_db.* TO 'my_user'@'localhost';
erteile
16

Ich habe eine interessante Lösung für Ihr Problem gefunden.
Tatsächlich können Sie für MySQL Berechtigungen für nicht vorhandene Datenbanken gewähren.
So können Sie in Ihren Einstellungen den Namen 'test_finance' für Ihre Testdatenbank hinzufügen:

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

Starten Sie die MySQL-Shell als Root-Benutzer:

mysql -u root -p

und gewähren Sie jetzt alle Berechtigungen für diese nicht vorhandene Datenbank in MySQL:

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

Jetzt startet Django problemlos Tests.

Yurii Halapup
quelle
4

Wenn die Datenbank MySQL ist, werden diese beiden Änderungen die Dinge erledigen.

1.Öffnen Sie mysite / mysite / settings.py

Ihre Datenbankeinstellungen sollten einen zusätzlichen TEST-Block haben, wie mit projectname_test gezeigt .

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

2.Geben Sie den folgenden Befehl über die Eingabeaufforderung mysql oder die mysql workbench ein , um dem in settings.py angegebenen Benutzer alle Berechtigungen zu erteilen

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

Jetzt kannst du rennen python manage.py test polls.

Chandan
quelle
Die Frage verwendet offensichtlich Postgres als DBMS. Worauf würde sich projectname_test beziehen?
Code-Kobold
@ code-kobold 7, Ja, aber ich kann den gleichen Fehler auch in MySQL sehen. Der Wert projectname_test bezieht sich auf den Namen des Projekts, z. B. in meiner Antwort ist es myproject.
Chandan
1

Wenn Sie das verwenden, docker-composewas für mich funktioniert hat, war das Folgende:

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

oder

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

Meine Einstellungen sehen folgendermaßen aus:

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

und mein docker-compose.ymlAussehen wie folgt:

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

In meinem Fall funktionierten GRANT PRIVILEGES-Lösungen nicht mit Python 3.7.2 , Django 2.1.7 und MySQL 5.6.23 ... Ich weiß nicht warum.

Also habe ich beschlossen, SQLite als TEST-Datenbank zu verwenden ...

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

Danach läuft das TESTS-Auto ohne Probleme:

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

Wow, so dass ich durch die Kombination aller Antworten hier mit ein wenig Optimierung endlich eine funktionierende Lösung für Docker-Compose, Django und Postgres gefunden habe ...

Erstens ist der von noufal valapra gegebene postgres-Befehl nicht korrekt (oder einfach nicht aktuell), er sollte sein:

ALTER USER docker WITH CREATEDB;

Im Fall eines Docker-Compose-Setups wird dies in der Datei init.sql gespeichert. So sieht meine aus:

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

Dann sieht das Dockerfile für Postgres folgendermaßen aus:

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

Dann hat die Django settings.py diesen Eintrag:

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

und das Docker-Compose sieht so aus:

Version: '3.6'

Dienstleistungen:

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

Vielleicht haben Sie Ihren Test in den Suspended-Modus oder als Hintergrundjob versetzt. Versuchen Sie es mit dem fgBefehl in der Bash-Shell.

eEmanuel Oviedo
quelle
0

Ein Superuser-Konto ist der einfachste Weg, um reibungslose Tests zu gewährleisten. Eine einfachere Möglichkeit, den djangoBenutzer su zu machen, besteht darin, dies zu tun ALTER django WITH SUPERUSER.

Weitere Informationen finden Sie unter https://www.postgresql.org/docs/current/sql-alteruser.html

ス ラ ッ シ ュ
quelle