使用call_command

时间:2017-08-03 02:22:13

标签: django

我在python 3.6上使用django 1.11。

我能解释问题的最简单方法是在代码中动态创建测试数据库。我使用以下脚本执行此操作:

from uuid import uuid4 as uuid
db = '_' + uuid().hex + 'db.sqlite3'
os.environ.setdefault('DJANGO_TEST_DB_NAME', db)
print(db)

import django
from django.apps import apps
from django.conf import settings
from django.core.management import call_command

os.environ.setdefault("DJANGO_SETTINGS_MODULE", "project.settings")
django.setup()

print("Setting up test database\n")

print("Clearing migrations...\n")
_dir = os.getcwd()
_search = ['project', 'email_auth', 'google', 'app2', 'app3']
for _d in _search:
    _walk = os.walk(_dir + os.path.sep + _d)
    for _walkObj in _walk:
        if _walkObj[0].split(os.path.sep)[-1] == 'migrations' or \
                (_walkObj[0].split(os.path.sep)[-2] == 'migrations' 
                and _walkObj[0].split(os.path.sep)[-1] == '__pycache__'):
            for _fName in _walkObj[2]:
                os.remove(_walkObj[0] + os.path.sep + _fName)

print("Calling manage:makemigrations\n")
call_command('makemigrations', *_search[1:])

apps.clear_cache()
apps.populate(settings.INSTALLED_APPS)

print("Calling manage:migrate...\n")
call_command('migrate')

print("Creating objects...\n")
call_command('create_objects')

print("Starting server...\n")
call_command('runserver')

无论我对apps对象做了什么(我尝试了一些hacky事情来清除其中的所有内容以重新加载,但没有骰子)或其他任何我无法让django意识到为我的任何一个创建了迁移调用迁移时的应用程序

我甚至尝试过调用migrate,email_auth,并指出django.core.management.base.CommandError: App 'email_auth' does not have migrations.

如果我在makemigrations部分之后取消它,我可以调用此脚本之外的迁移,它可以很好地迁移。

我强烈怀疑它无法正常工作,因为某处django有对模块的旧引用,我不知道如何更新它们。

编辑:

这样就证明它确实在迁移,我上传了一个控制台输出的粘贴框:https://pastebin.com/aSructTW

1 个答案:

答案 0 :(得分:0)

我终于想出了如何正确地做到这一点。请注意,要创建/使用测试数据库还有很多,但是这个问题的范围是重新加载应用程序。如果有人想要代码,请告诉我。以下是清除应用程序的功能:

def resetApps(search=[]):
    from collections import OrderedDict, defaultdict
    import os
    import sys
    from django.apps import apps
    from django.conf import settings

    apps.clear_cache()
    apps.all_models = defaultdict(OrderedDict)
    apps.app_configs = OrderedDict()
    apps.stored_app_configs = []
    apps.apps_ready = apps.models_ready = apps.ready = False
    apps._pending_operations = defaultdict(list)
    # clear out py caches of apps as we need to reload
    # modify this to allow removal of .pyc files that aren't in pycache, btw
    for _d in search:
        _walk = os.walk(_dir + os.path.sep + _d)
        for _walkObj in _walk:
            if _walkObj[0].split(os.path.sep)[-1] == '__pycache__':
                for _fName in _walkObj[2]:
                    os.remove(_walkObj[0] + os.path.sep + _fName)
    # clear out sys modules of required things
    _toClear = []
    for module in sys.modules:
        if module.split('.')[0] in search:
            _toClear.append(module)
    for module in _toClear:
        del sys.modules[module]
    apps.populate(settings.INSTALLED_APPS)