在服务器初始化时执行模型操作(仅一次) [英] Perform model operations (only once) at server init

查看:61
本文介绍了在服务器初始化时执行模型操作(仅一次)的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有一个非常特殊的要求:该应用程序应该能够显示其自身的正常运行时间(以总小时数表示).这意味着我需要离开请求-响应周期,并在相关模型中更新当前时间戳.

I have a rather peculiar requirement: The app should be able to display its own uptime as total hours. This means I need to step away from the request-response cycle and update the current timestamp in the relevant model.

考虑到这一点,我遵循了此处给出的说明. ,将代码放入我的应用程序apps.py中的ready()方法中.当然,问题是我遇到了Apps aren't loaded yet错误.我该如何解决?

With this in mind, I followed the instructions given here, putting the code in my app's ready() method in apps.py. The problem, of course, is that I ran into the Apps aren't loaded yet error. How do I work around this?

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

Another approach that comes to mind is do away with models and write the timestamp to a file, but this is a brittle method that will not scale. What if I want to store extensive relational information at boot time?

有人可以建议点什么吗?

Can someone suggest something, please?

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

======= UPDATE =========

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

The code I'm using is as follows (my project is called jremind and my app is called 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时的完整堆栈跟踪:

And here's the full stack trace when I run ./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.

推荐答案

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

You need to import the models from inside the method:

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

但是,您还应该注意警告文档:

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

Although you can access model classes as described above, avoid interacting with the database in your ready() implementation. This includes model methods that execute queries (save(), delete(), manager methods etc.)... Your ready() method will run during startup of every management command. For example, even though the test database configuration is separate from the production settings, manage.py test would still execute some queries against your production database!

也:

在通常的初始化过程中,Django只调用一次ready方法.但是在某些特殊情况下,尤其是在摆弄已安装的应用程序的测试中,准备可能会被多次调用.在这种情况下,请编写幂等方法,或在AppConfig类上放置一个标志,以防止重新运行应恰好执行一次的代码.

In the usual initialization process, the ready method is only called once by Django. But in some corner cases, particularly in tests which are fiddling with installed applications, ready might be called more than once. In that case, either write idempotent methods, or put a flag on your AppConfig classes to prevent re-running code which should be executed exactly one time.

将标记放置如下:

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

这篇关于在服务器初始化时执行模型操作(仅一次)的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆