django test app error - Got an error creating the

2019-01-29 21:11发布

问题:

When I try to test any app with command (I noticed it when I tried to deploy myproject using fabric, which uses this command):

python manage.py test appname

I get this 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

syncdb command seems to work. My database settings 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.
    }
}

回答1:

When Django runs the test suite, it creates a new database, in your case test_finance. The postgres user with username django does not have permission to create a database, hence the error message.

When you run migrate or syncdb, Django does not try to create the finance database, so you don't get any errors.

You can add the createdb permission to the django user by running the following command in the postgres shell as a superuser (hat tip to this stack overflow answer).

=> ALTER USER django CREATEDB;

Note: The username used in the ALTER USER <username> CREATEDB; command needs to match the database user in your Django settings files. In this case, the original poster, had the user as django the above answer.



回答2:

I have found interesting solution to your problem.
In fact for MySQL you can grant privileges for non-existing database.
So you can add name 'test_finance' for your test database in your settings:

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

start MySQL shell as the root user:

mysql -u root -p

and now grant all privileges to this non-existing database in MySQL:

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

Now Django will start tests without any problems.



回答3:

In the case of Postgres, the user must have createdb permission.

ALTER ROLE miriam CREATEDB;

See this documentation: https://docs.djangoproject.com/en/2.0/topics/testing/overview/#the-test-database



回答4:

If database is mysql then these two changes will get the things done.

1.Open mysite/mysite/settings.py

Your database settings should have an additional TEST block as shown with projectname_test.

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

2.Type the below command using mysql command prompt or mysql workbench to give all privilages to the user specified in settings.py

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

Now you can run python manage.py test polls.



回答5:

If you are using docker-compose what worked for me was the following:

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

or

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

My settings looks like this:

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

and my docker-compose.yml looks as follows:

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"