【问题标题】:django test app error - Got an error creating the test database: permission denied to create databasedjango test app error - 创建测试数据库时出错:创建数据库的权限被拒绝
【发布时间】:2012-12-20 14:21:28
【问题描述】:

当我尝试使用命令测试任何应用程序时(我在尝试使用使用此命令的结构部署我的项目时注意到了这一点):

python manage.py test appname

我收到此错误:

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 命令似乎有效。我在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.
    }
}

【问题讨论】:

    标签: python sql django postgresql django-testing


    【解决方案1】:

    当 Django 运行测试套件时,它会创建一个新数据库,在您的情况下为 test_finance。用户名为 django 的 postgres 用户无权创建数据库,因此出现错误消息。

    当您运行migratesyncdb 时,Django 不会尝试创建finance 数据库,因此您不会收到任何错误。

    您可以通过在 postgres shell 中以超级用户身份运行以下命令,为 django 用户添加 createdb 权限(提示this stack overflow answer)。

    => ALTER USER django CREATEDB;
    

    注意:ALTER USER <username> CREATEDB; 命令中使用的用户名需要与 Django 设置文件中的数据库用户匹配。在这种情况下,原始发帖人的用户为django上述答案。

    【讨论】:

    • 虽然 OP 使用了 postgresql,但如果你使用的是 mysql,你也会遇到同样的错误。您可以使用以下方法为 mysql 修复它: => GRANT ALL ON *.* TO django@localhost;我最初尝试只 GRANT CREATE... 但后来无法 SELECT 或 DROP 创建的数据库。这实际上使您的用户成为超级用户,所以要小心。
    • 我做了一些实验,发现最小的全局权限是 - 数据:SELECT、INSERT、UPDATE、DELETE,结构:CREATE、ALTER、INDEX、DROP,管理员:REFERENCES。不是超级用户,但仍然很强大,所以要小心。
    • 就我而言,我授予测试数据库的所有权限,如下所示:GRANT ALL PRIVILEGES ON test_my_db.* TO 'my_user'@'localhost';
    【解决方案2】:

    我为您的问题找到了有趣的解决方案。
    事实上,对于 MySQL,您可以为不存在的数据库授予权限。
    因此,您可以在设置中为您的测试数据库添加名称“test_finance”:

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

    以 root 用户身份启动 MySQL shell:

    mysql -u root -p
    

    现在授予 MySQL 中这个不存在的数据库的所有权限:

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

    现在 Django 将毫无问题地开始测试。

    【讨论】:

    • 我在 mysql shell 中得到 ERROR 1410 (42000): You are not allowed to create a user with GRANT。请问有什么办法吗?
    • 如你所见,我已经以 root 用户身份启动 MySQL shell。
    【解决方案3】:

    对于 Postgres,用户必须拥有createdb 权限。

    ALTER ROLE miriam CREATEDB;
    

    请参阅此文档:https://docs.djangoproject.com/en/2.0/topics/testing/overview/#the-test-database

    【讨论】:

      【解决方案4】:

      如果数据库是mysql,那么这两个更改将完成。

      1.打开mysite/mysite/settings.py

      您的数据库设置应该有一个额外的 TEST 块,如 projectname_test 所示。

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

      2.使用mysql command promptmysql workbench键入以下命令,将所有权限授予settings.py中指定的用户

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

      现在你可以运行python manage.py test polls

      【讨论】:

      • 这个问题显然使用 Postgres 作为 DBMS。 projectname_test 与什么相关?
      • @code-kobold 7,是的,但我也可以在 mysql 中看到相同的错误。值 projectname_test 是指项目名称,在我的回答中是 myproject。
      【解决方案5】:

      就我而言,GRANT PRIVILEGES 解决方案不适用于 Python 3.7.2Django 2.1.7MySQL 5.6.23 ...我不知道为什么。

      所以我决定使用 SQLite 作为 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'),
              },
          }
      }
      

      之后,TESTS 车无故障运行:

      $ 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
      

      【讨论】:

      • 起初,这似乎是个好主意。但我试过了,它似乎不起作用。我现在在文档中看到在TESTis not an option 中指定ENGINE。另外,我注意到您注释掉了 MySQL 后端并添加了连接器。那是什么?
      • 您似乎在生产和测试环境中使用了不同的数据库。这可能不是一个好主意,并且可能导致特定于数据库的错误。
      【解决方案6】:

      哇,结合这里的所有答案并稍加调整,终于让我找到了适用于 docker-compose、django 和 postgres 的工作解决方案...

      首先 noufal valapra 给出的 postgres 命令不正确(或者可能只是不是当前的),它应该是:

      ALTER USER docker WITH CREATEDB;
      

      在 docker-compose 设置的情况下,这将进入 init.sql 文件,这就是我的样子:

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

      那么用于 postgres 的 Dockerfile 如下所示:

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

      那么 Django settings.py 就有这个条目:

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

      docker-compose 看起来像这样:

      版本:'3.6'

      服务:

      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:
      

      【讨论】:

        【解决方案7】:

        如果您使用的是docker-compose,对我有用的是:

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

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

        我的设置如下所示:

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

        而我的docker-compose.yml 如下所示:

        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"
        

        【讨论】:

          【解决方案8】:

          超级用户帐户是保证顺利测试的最简单方法。所以制作django用户su的更简单的方法是ALTER django WITH SUPERUSER

          更多信息https://www.postgresql.org/docs/current/sql-alteruser.html

          【讨论】:

          • ALTER USER django WITH SUPERUSER,您忘记了 USER 关键字。我尝试编辑您的帖子,但编辑队列已满,无法释放。
          【解决方案9】:

          检查运行时的动作并切换数据库

          import sys
          TESTING = sys.argv[1:2] == ['test']
          if TESTING==False:
              DATABASES = {
                  'default': {
                      'ENGINE': 'django.db.backends.postgresql_psycopg2',
                      'NAME': config('DB_NAME'),
                      'USER': config('DB_USER'),
                      'PASSWORD': config('DB_PASSWORD'),
                      'HOST': config('DB_HOST'),
                      'PORT': ''
                       }       
                     }
          else:
              DATABASES = {    
                  'default': {
                  "ENGINE": "django.db.backends.sqlite3",
                  "TEST": {
                      "NAME": os.path.join(BASE_DIR, "test_db.sqlite3"),
                  }
              }}
          

          【讨论】:

            【解决方案10】:

            也许您将测试置于暂停模式或作为后台作业。尝试在 bash shell 中使用 fg 命令。

            【讨论】:

              【解决方案11】:

              您也可以手动创建一个测试数据库,但将 TEST 键放在您的 settings.py 中

              然后用值“default”填充传递 MIRROR 键,以便您可以测试默认数据库的精确副本,或者您喜欢的任何数据库。

              DATABASES = {
                  'default': {
                      'ENGINE': 'django.db.backends.postgresql_psycopg2',
                      'NAME': 'finance',
                      'USER': 'django',
                      'TEST': {
                           'MIRROR': 'default',
                      },
                      'PASSWORD': 'mydb123',
                      'HOST': '127.0.0.1',
                      'PORT': '',
                  }
              }
              

              您也可以查看advanced django postgres docs

              【讨论】:

              • 这是一种错误的做法,因为会使用真实的数据库将持久性数据写入数据库。之后无法删除。
              【解决方案12】:

              键入以下内容切换到服务器上的 postgres 帐户:

              sudo -i -u postgres
              

              您现在可以通过键入以下内容立即访问 Postgres 提示:

              psql
              

              现在输入

              ALTER USER username CREATEDB;
              

              【讨论】:

                猜你喜欢
                • 2022-01-16
                • 1970-01-01
                • 2017-01-26
                • 1970-01-01
                • 2014-03-25
                • 2017-09-29
                • 1970-01-01
                • 1970-01-01
                • 1970-01-01
                相关资源
                最近更新 更多