从接触数据库的 类 解耦 Django 信号
Decoupling Django signals from classes that touch the DB
我有一个发送信号的应用程序,我们称它为 signal_x
。在另一个应用程序中,为 signal_x
定义了一个 @receiver
,在它的 apps.py 中,ready()
函数是包含接收机进口。
@receiver
函数有一个问题。它依赖于一个对象,我们称之为 object_y
,它的构造函数依赖于 DB。使用从数据库中提取的值,构建了一些重对象。这些 heavy_objects 必须在内存中,以便进行非常快速的计算,因此它们不能延迟加载,因为它们在第一次使用时会花费太长时间。 self.location_ids
也不能延迟加载,因为它被两个 compute_heavy_... 函数使用。
一切正常,直到我们删除数据库,重新创建它并 运行 manage.py makemigrations。现在 makemigrations 将失败,因为 Django 首先 运行s django.setup()
,运行s 每个应用程序的 ready()
函数。当它通过导入到达 ready()
函数时,它将按预期导入文件并尝试创建 object_y
。但是 object_y
需要尚不存在的模型,因此会出现错误。我怎么能优雅地solve/circumvent这个?
class Recommender:
def __init__(self):
self.location_ids = self.get_location_ids()
self.heavy_object1 = self.compute_heavy_object1(location_ids)
self.heavy_object2 = self.compute_heavy_object2(..., location_ids)
def get_location_ids():
locations = LocationNode.objects.filter(level=1, parent_id=1)
return [location.id for location in locations]
... meantime in another file
object_y = Recommender()
@receiver(signal_x, dispatch_uid="update_state")
def recompute(sender, **kwargs):
client_id = kwargs['client_id']
# prepare some things
heavy_recompute(object_y, client_id)
这是一个常见的用例。由于您没有提供那么多代码,因此很难给您一个非常准确的答案,但是,考虑一下:
- 在
AppConfig.ready()
函数中,您应该始终使用 self.get_model()
to retrieve a reference to a model defined in another app. This will ensure the app registry is up-to-date if require_ready=True
(the default). Outside a AppConfig
method, you can use apps.get_model()
- 不要在模块级别创建模型实例 (
object_y = HeavyObject()
)。注意:我不知道 HeavyObject
是不是 Django 模型。但一般情况下,你可以默认声明object_y = None
,稍后再初始化变量
我有一个发送信号的应用程序,我们称它为 signal_x
。在另一个应用程序中,为 signal_x
定义了一个 @receiver
,在它的 apps.py 中,ready()
函数是包含接收机进口。
@receiver
函数有一个问题。它依赖于一个对象,我们称之为 object_y
,它的构造函数依赖于 DB。使用从数据库中提取的值,构建了一些重对象。这些 heavy_objects 必须在内存中,以便进行非常快速的计算,因此它们不能延迟加载,因为它们在第一次使用时会花费太长时间。 self.location_ids
也不能延迟加载,因为它被两个 compute_heavy_... 函数使用。
一切正常,直到我们删除数据库,重新创建它并 运行 manage.py makemigrations。现在 makemigrations 将失败,因为 Django 首先 运行s django.setup()
,运行s 每个应用程序的 ready()
函数。当它通过导入到达 ready()
函数时,它将按预期导入文件并尝试创建 object_y
。但是 object_y
需要尚不存在的模型,因此会出现错误。我怎么能优雅地solve/circumvent这个?
class Recommender:
def __init__(self):
self.location_ids = self.get_location_ids()
self.heavy_object1 = self.compute_heavy_object1(location_ids)
self.heavy_object2 = self.compute_heavy_object2(..., location_ids)
def get_location_ids():
locations = LocationNode.objects.filter(level=1, parent_id=1)
return [location.id for location in locations]
... meantime in another file
object_y = Recommender()
@receiver(signal_x, dispatch_uid="update_state")
def recompute(sender, **kwargs):
client_id = kwargs['client_id']
# prepare some things
heavy_recompute(object_y, client_id)
这是一个常见的用例。由于您没有提供那么多代码,因此很难给您一个非常准确的答案,但是,考虑一下:
- 在
AppConfig.ready()
函数中,您应该始终使用self.get_model()
to retrieve a reference to a model defined in another app. This will ensure the app registry is up-to-date ifrequire_ready=True
(the default). Outside aAppConfig
method, you can useapps.get_model()
- 不要在模块级别创建模型实例 (
object_y = HeavyObject()
)。注意:我不知道HeavyObject
是不是 Django 模型。但一般情况下,你可以默认声明object_y = None
,稍后再初始化变量