Django 在单独的数据库上进行测试,给出“OperationalError:没有这样的表:auth_user”

Posted

技术标签:

【中文标题】Django 在单独的数据库上进行测试,给出“OperationalError:没有这样的表:auth_user”【英文标题】:Django testing on separate database giving "OperationalError: no such table: auth_user" 【发布时间】:2016-11-18 08:41:33 【问题描述】:

我的问题是我想建立一个单独的测试数据库,与我的开发数据库分开。应用程序本身与 Django-Rest-Framework 快速入门教程几乎相同,只是我使用 LDAP 后端。我的开发数据库使用 mysql。我有单独的设置文件进行测试。

我在这里输入的完整错误回溯:http://dpaste.com/1W3TX1E,但有趣的部分是:

sqlite3.OperationalError: no such table: auth_user

完整的测试设置在这里:http://dpaste.com/1K7KHK4。我的相关设置是(已安装的应用程序中缺少 pyldap 和 django-ldap-auth,它们是使用 pip 手动安装的):

    INSTALLED_APPS = [
    'django.contrib.admin',
    'django.contrib.auth',
    'django.contrib.contenttypes',
    'django.contrib.sessions',
    'django.contrib.messages',
    'django.contrib.staticfiles',
    'rest_framework',
    'njord',
    'permissions',
]
DATABASES = 
    'default': 
        'ENGINE': 'django.db.backends.sqlite3',
        'NAME': ':memory:',
    

目前,该应用程序基本上只使用 LDAP 进行身份验证。我认为这就是我出错的原因——当我进行测试时,我的数据库中什么都没有——没有用户,没有组。如果用户通过 LDAP 服务器进行身份验证,则会在数据库中创建用户以及他/她所在的所有组,因此它是按需发生的。

什么有效:我的应用程序的开发版本适用于外部 LDAP,并且测试也适用于开发数据库。

什么不起作用:使用 sqllite3 内存数据库进行测试(我重复一遍,使用开发数据库和模拟 ldap 进行测试)。

我测试的代码在这里:

from django.test import TestCase, Client
import django
import ldap

from mockldap import MockLdap

class AuthenticationTests(TestCase):
    """
    Set Up the structure  ( Accounts, Groups ) and try authentication
    """
    # Top level hierarchy
    top = ('dc=ee', 'dc': ['ee'])
    test = ('dc=test,dc=ee', 'dc': ['test'])

    # Top level groups
    people = ('ou=people,dc=test,dc=ee', 'ou': ['people'], 'objectClass': ['organizationalUnit', 'top'])
    groups = ('ou=groups,dc=test,dc=ee', 'ou': ['groups'], 'objectClass': ['organizationalUnit', 'top'])

    # Groups
    admins = ('cn=admins,ou=groups,dc=test,dc=ee', 'cn': ['admins'], 'memberUid': ['admin'],
                                                'objectClass': ['sambaGroupMapping', 'posixGroup', 'top'],
                                                'gidNumber': ['1'])

    group1 = ('cn=group1,ou=groups,dc=test,dc=ee', 'cn': ['group1'],
                                                'memberUid': ['alice', 'bob'],
                                      'objectClass': ['sambaGroupMapping', 'posixGroup', 'top'])

    group2 = ('cn=group2,ou=groups,dc=test,dc=ee', 'cn': ['group2'], 'memberUid': ['admin', 'bob', 'karl'],
                                      'objectClass': ['sambaGroupMapping', 'posixGroup', 'top'])

    # Users
    admin = ('uid=admin,ou=people,dc=test,dc=ee', 'uid': ['admin'], 'userPassword': ['ldaptest'], 'sn': ['Joe'],
                                               'cn': ['Admin Joe'], 'mail': ['admin.joe@test.ee'],
                                               'givenName': ['Admin'], 'objectClass':
                                                   ['top', 'person', 'posixAccount', 'shadowAccount',
                                                    'inetOrgPerson', 'sambaSamAccount'])

    alice = ('uid=alice,ou=people,dc=test,dc=ee', 'uid': ['alice'], 'userPassword': ['ldaptest'], 'sn': ['Cooper'],
                                               'cn': ['Alice Cooper'], 'mail': ['alice.cooper@test.ee'],
                                               'givenName': ['Alice'], 'objectClass':
                                                   ['top', 'person', 'posixAccount', 'shadowAccount',
                                                    'inetOrgPerson', 'sambaSamAccount'])

    bob = ('uid=bob,ou=people,dc=test,dc=ee', 'uid': ['bob'], 'userPassword': ['ldaptest'], 'sn': ['Marley'],
                                           'cn': ['Bob Marley'], 'mail': ['bob.marley@test.ee'],
                                           'givenName': ['Bob'], 'objectClass':
                                               ['top', 'person', 'posixAccount', 'shadowAccount',
                                                'inetOrgPerson', 'sambaSamAccount'])

    karl = ('uid=karl,ou=people,dc=test,dc=ee', 'uid': ['karl'], 'userPassword': ['ldaptest'], 'sn': ['Suur'],
                                             'cn': ['Karl Suur'], 'mail': ['karl.suur@test.ee'],
                                             'givenName': ['Karl'], 'objectClass':
                                                 ['top', 'person', 'posixAccount', 'shadowAccount',
                                                  'inetOrgPerson', 'sambaSamAccount'])

    # This is the content of our mock LDAP directory. It takes the form
    # dn: attr: [value, ...], ..., ....
    directory = dict([top, test, people, groups, admins, group1, group2, admin, alice, bob, karl])

    @classmethod
    def setUpTestData(cls):
        # We only need to create the MockLdap instance once. The content we
        # pass in will be used for all LDAP connections.
        cls.mockldap = MockLdap(cls.directory)

    @classmethod
    def tearDownClass(cls):
        del cls.mockldap

    def setUp(self):
        # Patch ldap.initialize
        django.setup()
        self.mockldap.start()
        self.ldapobj = self.mockldap['ldap://localhost/']

    def tearDown(self):
        # Stop patching ldap.initialize and reset state.
        self.mockldap.stop()
        del self.ldapobj

    def test_some_basic_mockldap_auth(self):
        searchStr = 'uid=alice,ou=people,dc=test,dc=ee'
        results = _do_simple_ldap_search(searchStr)
        ldapName = results[0][0]
        ldapPropDict = results[0][1]
        self.assertEqual(searchStr, ldapName)
        self.assertEqual(len(ldapPropDict), 7)

    def test_index_visible_for_all(self):
        c = Client()
        response = c.get("/")
        self.assertContains(response, "/users/", 1)
        self.assertContains(response, "/groups/", 1)

    def test_login(self):
        c = Client()
        response = c.post("/api-auth/login/", 'username': 'bob', 'password': 'ldaptest')
        print(response.status_code)
        response = c.get("/users/")
        print(response._container)

def _do_simple_ldap_search(searchStr):
    conn = ldap.initialize('ldap://localhost/')
    conn.simple_bind_s(searchStr, 'ldaptest')
    results = conn.search_s(searchStr, ldap.SCOPE_SUBTREE, )

    return results

这里也提供代码:http://dpaste.com/3D2H4NK(语法高亮)。

我不确定,问题是什么。我唯一能想到的是,因为创建时数据库中没有用户,所以没有创建数据库,但我不确定。任何帮助深表感谢。

我已经完成了所有的迁移。

(venv)user@box:~/workspace/fileshare/njord$ python manage.py showmigrationsadmin
 [X] 0001_initial
 [X] 0002_logentry_remove_auto_add
auth
 [X] 0001_initial
 [X] 0002_alter_permission_name_max_length
 [X] 0003_alter_user_email_max_length
 [X] 0004_alter_user_username_opts
 [X] 0005_alter_user_last_login_null
 [X] 0006_require_contenttypes_0002
 [X] 0007_alter_validators_add_error_messages
contenttypes
 [X] 0001_initial
 [X] 0002_remove_content_type_name
sessions
 [X] 0001_initial
(venv)user@box:~/workspace/fileshare/njord$ python manage.py makemigrationsNo changes detected
(venv)user@box:~/workspace/fileshare/njord$ python manage.py migrate
Operations to perform:
  Apply all migrations: admin, sessions, auth, contenttypes
Running migrations:
  No migrations to apply.

【问题讨论】:

【参考方案1】:

运行python manage.py makemigrations <appname> 对于INSTALLED_APPS 中的每个应用程序。(特别是在auth_user 上具有 ForeignKey 字段的应用程序)

我在这里遇到了不同的错误,但认为原因是相同的。django.db.utils.OperationalError: (1005, "Can't create table '<test_db>.#sql-3821_1c9' (errno: 150)")

在这两种情况下,所有与auth模块相关的表都只是在测试时不创建,不执行makemigrations命令。 我从here找到了解决方案

【讨论】:

【参考方案2】:

必须做的就是将这些行添加到 manage.py:

if __name__ == "__main__":
    if 'test' in sys.argv:
        os.environ.setdefault("DJANGO_SETTINGS_MODULE", "app.test_settings")
    else:
        os.environ.setdefault("DJANGO_SETTINGS_MODULE", "app.settings")

在 manage.py 的 main 方法中添加 if 'test' 之后,应用程序开始正常工作,之后 python manage.py test 和 python manage.py runserver 都使用正确的设置。

但是,我还没有让它与 PyCharm 一起工作,现在测试它,如何让它工作。

【讨论】:

以上是关于Django 在单独的数据库上进行测试,给出“OperationalError:没有这样的表:auth_user”的主要内容,如果未能解决你的问题,请参考以下文章

在单独的线程上进行 iPhone CoreLocation 调用的最佳方法?

在单独的 Web Api 上进行 JWT 验证

Simplemembership ASPXAUTH cookie 在两个单独的 Web 项目上进行验证

如何在 django 的类视图上进行身份验证

在 django 上进行迁移后无法迁移

使用跨越关系的字段查找在 django 模型上进行链式过滤和排除