在服务器初始化

时间:2016-07-13 02:40:07

标签: django django-1.9

我有一个相当特殊的要求:应用程序应该能够将自己的正常运行时间显示为总小时数。这意味着我需要远离请求 - 响应周期并更新相关模型中的当前时间戳。

考虑到这一点,我按照here给出的说明,将代码放在ready()中我应用的apps.py方法中。当然,问题是我遇到了Apps aren't loaded yet错误。我该如何解决这个问题?

另一种想到的方法是取消模型并将时间戳写入文件,但这是一种无法扩展的脆弱方法。如果我想在启动时存储大量关系信息怎么办?

有人可以提出建议吗?

=======更新=========

我正在使用的代码如下(我的项目名为jremind,我的应用程序名为remind)。

这是我的模型实例:

class Monitor(models.Model):
    # save automatically when object is saved()
    app_init_timestamp = models.DateTimeField(null=False, auto_now=True)

应用的__init__文件:

default_app_config = 'remind.apps.RemindConfig'

应用的apps.py文件:

from django.apps import AppConfig
from remind.models import Monitor

class RemindConfig(AppConfig):
    name = 'remind'

    def ready(self):
        # There's only one instance
        monitor = Monitor.objects.get()[0]
        #Auto-update timestamp
        monitor.save()

当我运行./manage.py runserver时,这是完整的堆栈跟踪:

(env) jremind$ ./manage.py runserver
Performing system checks...

System check identified no issues (0 silenced).
July 13, 2016 - 15:12:08
Django version 1.9, using settings 'jremind.settings'
Starting development server at http://127.0.0.1:8000/
Quit the server with CONTROL-C.
^C(env) jremind$ ./manage.py runserver
Traceback (most recent call last):
  File "./manage.py", line 10, in <module>
    execute_from_command_line(sys.argv)
  File "/media/common/code/python/projects/jremind/env/lib/python3.4/site-packages/django/core/management/__init__.py", line 350, in execute_from_command_line
    utility.execute()
  File "/media/common/code/python/projects/jremind/env/lib/python3.4/site-packages/django/core/management/__init__.py", line 342, in execute
    self.fetch_command(subcommand).run_from_argv(self.argv)
  File "/media/common/code/python/projects/jremind/env/lib/python3.4/site-packages/django/core/management/__init__.py", line 176, in fetch_command
    commands = get_commands()
  File "/media/common/code/python/projects/jremind/env/lib/python3.4/functools.py", line 448, in wrapper
    result = user_function(*args, **kwds)
  File "/media/common/code/python/projects/jremind/env/lib/python3.4/site-packages/django/core/management/__init__.py", line 71, in get_commands
    for app_config in reversed(list(apps.get_app_configs())):
  File "/media/common/code/python/projects/jremind/env/lib/python3.4/site-packages/django/apps/registry.py", line 137, in get_app_configs
    self.check_apps_ready()
  File "/media/common/code/python/projects/jremind/env/lib/python3.4/site-packages/django/apps/registry.py", line 124, in check_apps_ready
    raise AppRegistryNotReady("Apps aren't loaded yet.")
django.core.exceptions.AppRegistryNotReady: Apps aren't loaded yet.

1 个答案:

答案 0 :(得分:2)

您需要从方法内导入模型:

def ready(self):
    from remind.models import Monitor

但是,您还应该注意warning in the documentation

  

虽然您可以按上述方法访问模型类,但请避免在ready()实现中与数据库进行交互。这包括执行查询的模型方法(save()delete(),管理器方法等。)...您的ready()方法将在每个管理命令启动期间运行。例如,即使测试数据库配置与生产设置分开,manage.py test仍然会对生产数据库执行一些查询!

另外:

  

在通常的初始化过程中,ready方法仅由Django调用一次。但是在某些极端情况下,特别是在摆弄已安装应用程序的测试中,就可以不止一次调用ready。在这种情况下,要么写出幂等方法,要么在AppConfig类上放置一个标志,以防止重新运行应该执行一次的代码。

举旗会这样做:

class RemindConfig(AppConfig):
    name = 'remind'
    ready_has_run = False

    def ready(self):
        if self.ready_has_run:
            return

        # Do your stuff here, and then set the flag
        self.ready_has_run = True