【问题标题】:Django 1.7 Models aren't loaded yet when getting foreign key field获取外键字段时尚未加载 Django 1.7 模型
【发布时间】:2016-05-25 20:35:54
【问题描述】:

我有一个类将由项目__init__.py 调用(因为我想在django 网站启动时将值保存在内存中):

def get_rec(**karg):
    try: 
       if len(karg) == 0:
          return Gateway.objects.all()
       else:
          return Gateway.objects.filter(**karg)
    except as e:
       log.error(e)
       return []

Class test(object):

    def __init_rec_list(object):
        rec = get_rec()
        for r in rec:
            print r.mac_address
            print r.area.area_name

但是在尝试打印r.area.area_name时会报错:

  raise AppRegistryNotReady("Models aren't loaded yet.")
django.core.exceptions.AppRegistryNotReady: Models aren't loaded yet.

为什么不能打印r.area.area_name??

这是models.py

class Area(models.Model):
    area_name = models.CharField(max_length=255, null=False, blank=False)

class Gateway(models.Model):  
    mac_address = models.CharField(max_length=50, null=False, blank=False)
    area = models.ForeignKey(Area,null=True,blank=True,related_name = 'area')

【问题讨论】:

    标签: python django django-1.7


    【解决方案1】:

    错误说得很清楚 - 模型还没有准备好。可以接触数据库的较早时刻在AppConfig.ready,但仍有一些限制。

    如果您想安全使用所有模型,请将代码放入项目根目录下的urls.py

    【讨论】:

      【解决方案2】:

      通过在__init__.py 文件中调用模型,您正在创建一个先有鸡还是先有蛋的场景。初始化代码要求模型准备好,模型正在等待__init__.py 准备好。

      __init__.py 文件中调用此类代码不是一个好习惯。因为这个文件不仅会在 django 启动时加载,而且在您导入模块时也会加载。

      从您的代码中,我可以看到您正在尝试基于此访问用户 ip 和其他信息。

      最好的方法是使用自定义 middleware 拦截 request/response 并根据值更新 request/response 对象。

      类似的东西 -

      class CustomMiddleware(object):
          def process_request(self, request):
              rec = get_rec()
              request.rec = rec;
      

      现在您可以访问request 的属性rec 并随意使用。

      您可以在此处阅读有关中间件的更多信息 -

      https://docs.djangoproject.com/en/1.7/topics/http/middleware/

      【讨论】:

      • 如果一个动作在启动时只需要一次,最好不要把它放在每个请求都运行的中间件中
      • @AviahLaor 同意了,但是我没有回答要在内存中放入一些东西以供启动,我回答了 OP 的场景,跟踪 mac,最好在每个请求中都这样做。用户可以轻松更改 mac,这与 django 启动无关。
      【解决方案3】:

      你应该在 django 加载后调用依赖于 django 的初始化代码。只有当 django.setup() 运行时,App 注册表才准备就绪。

      假设您有默认的 wsgi.py 文件,正确的入口点在 wsgi.py 中:

      import os
      from django.core.wsgi import get_wsgi_application
      os.environ.setdefault("DJANGO_SETTINGS_MODULE", "mysite.settings")    
      application = get_wsgi_application() # this prepares django 
      my_init_code()
      

      如果您绝对需要在模型加载之前运行一些东西,请使用直接 SQL 到数据库。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2014-10-21
        • 2020-07-06
        • 1970-01-01
        • 2014-10-30
        • 1970-01-01
        • 2018-11-07
        • 2020-06-30
        • 2016-03-11
        相关资源
        最近更新 更多