django test app error - Erro ao criar o banco de dados de teste: permissão negada para criar banco de dados


181

Quando tento testar qualquer aplicativo com comando (notei quando tentei implantar meu projeto usando fabric, que usa este comando):

python manage.py test appname

Eu recebo este erro:

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

syncdbcomando parece funcionar. Minhas configurações de banco de dados em 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.
    }
}

Respostas:


373

Quando o Django executa a suíte de testes, ele cria um novo banco de dados, no seu caso test_finance. O usuário do postgres com nome de usuário djangonão tem permissão para criar um banco de dados, daí a mensagem de erro.

Quando você executa migrateou syncdb, o Django não tenta criar o financebanco de dados, para que você não obtenha nenhum erro.

Você pode adicionar a permissão createdb ao usuário django executando o seguinte comando no shell do postgres como superusuário (dica de chapéu para esta resposta de estouro de pilha ).

=> ALTER USER django CREATEDB;

Nota: O nome de usuário usado no ALTER USER <username> CREATEDB;comando precisa corresponder ao usuário do banco de dados nos arquivos de configuração do Django. Nesse caso, o pôster original teve o usuário como djangoresposta acima.


2
Embora o OP tenha usado o postgresql, se você estiver usando o mysql, terá o mesmo erro. Você pode corrigi-lo no mysql com: => GRANT ALL ON *. * TO django @ localhost; Inicialmente, tentei apenas GRANT CREATE ... mas não consegui SELECT ou DROP o banco de dados criado. Isso essencialmente torna seu usuário um superusuário, portanto, tenha cuidado.
Mightypile

1
Eu experimentei um pouco e descobri que os privilégios globais mínimos são - Dados: SELECT, INSERT, UPDATE, DELETE, Estrutura: CREATE, ALTER, INDEX, DROP, Admin: REFERENCES. Não é um superusuário, mas ainda é bastante poderoso, portanto, tenha cuidado.
Scott Scott

no meu caso, concedo todos os privilégios ao banco de dados de teste, algo como isto:GRANT ALL PRIVILEGES ON test_my_db.* TO 'my_user'@'localhost';
Yacine Rouizi

17

Encontrei uma solução interessante para o seu problema.
De fato, para o MySQL, você pode conceder privilégios para bancos de dados inexistentes.
Portanto, você pode adicionar o nome 'test_finance' ao seu banco de dados de teste nas suas configurações:

    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 o shell MySQL como usuário root:

mysql -u root -p

e agora conceda todos os privilégios a esse banco de dados inexistente no MySQL:

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

Agora o Django iniciará os testes sem problemas.



4

Se o banco de dados for mysql , essas duas alterações farão as coisas.

1.Abra mysite / mysite / settings.py

As configurações do seu banco de dados devem ter um bloco TEST adicional, como mostrado em projectname_test .

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

2. Digite o comando abaixo usando o prompt de comando mysql ou o mysql workbench para conceder todos os privilégios ao usuário especificado em settings.py

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

Agora você pode correr python manage.py test polls.


A questão obviamente usa o Postgres como DBMS. Com o que o projectname_test se relacionaria?
code-Kobold

@ code-kobold 7, Sim, mas também vejo o mesmo erro no mysql.O valor projectname_test é o nome do projeto ex.em minha resposta, é meu projeto.
30417 Chandan

1

Se você está usando o docker-composeque funcionou para mim, foi o seguinte:

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

ou

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

Minhas configurações são assim:

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

e minha docker-compose.ymlaparência da seguinte maneira:

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"

1

No meu caso, as soluções GRANT PRIVILEGES não funcionaram com Python 3.7.2 , Django 2.1.7 e MySQL 5.6.23 ... Não sei por que.

Então, eu decidi usar o SQLite como um banco de dados de teste ...

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

Depois disso, o carro TESTES roda sem 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

0

Uau, então, combinar todas as respostas aqui com um pouco de ajuste finalmente me levou a uma solução de trabalho para docker-composite, django e postgres ...

Primeiro, o comando postgres dado por noufal valapra não está correto (ou talvez não seja atual), deve ser:

ALTER USER docker WITH CREATEDB;

No caso de uma configuração de docker-compose, isso irá para o arquivo init.sql, é assim que o meu se parece:

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

Em seguida, o Dockerfile para postgres fica assim:

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

Então o Django settings.py tem 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'],
        }
    }

e a janela de encaixe-composição fica assim:

versão: '3.6'

Serviços:

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

Talvez você faça seu teste no modo suspenso ou como um trabalho em segundo plano. Tente com o fgcomando no bash shell.


Ao utilizar nosso site, você reconhece que leu e compreendeu nossa Política de Cookies e nossa Política de Privacidade.
Licensed under cc by-sa 3.0 with attribution required.