django - 在服务器初始化时执行模型操作(仅一次)

标签 django django-1.9

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

考虑到这一点,我按照 here 给出的说明进行操作。 ,将代码放入我的应用程序的 apps.py 中的 ready() 方法中。当然,问题是我遇到了应用程序尚未加载错误。我该如何解决这个问题?

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

有人可以建议一下吗?

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

我使用的代码如下(我的项目称为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.

最佳答案

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

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

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

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!

另外:

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

关于django - 在服务器初始化时执行模型操作(仅一次),我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/38341793/

相关文章:

python - 将 GET 请求参数转换为 int ... 如果它是数字

javascript - 重定向中断图像上传

python - 创建管理员限制的网址

django - 使用 django 的 PostgreSQL IP inet 比较

mysql - djangos unique=true 实际上做了什么?

django - "Unknown command syncdb"运行 "python manage.py syncdb"

python - Django 1.9 如何在 __init__.py 中导入

python - django-eav 和南方

json - Django 如何使用 SplitJSONWidget 保存/编辑 json

python - 无法使用 django 连接到本地 Postgresql 服务器