2016-05-11 74 views
1

我试图找到一种方法来在Django模型中存储函数。 我的用例是一个带有计划和有条件发送的电子邮件系统。 “如果约翰还没有登录,明天发送此电子邮件”Django,数据库中的存储功能

“明天发送此电子邮件。

理想情况下,我想创建带有测试功能字段的电子邮件。

def my_test(instance): 
    if (now() - instance.user.last_login) > timedelta(days=1): 
    return False 
    return True 

Email(send_later_date=now() + timedelta(days=1), 
     conditional=my_test) 

这里就是我想

import importlib 

Email(send_later_date=now() + timedelta(days=1), 
     conditional='my_app.views.my_test') 



class Email(models.Model): 
    send_later_date = models.DateTimeField(null=True, blank=True) 
    conditional = models.TextField() 

    def send_email(self): 
    if self.send_later_date < now(): 
     if not self.conditional: 
     function_send_email() 
     else: 
     function_string = self.conditional 
     mod_name, func_name = function_string.rsplit('.',1) 
     mod = importlib.import_module(mod_name) 
     func = getattr(mod, func_name) 
     if func(): 
      function_send_email() 

你会怎么做呢?我正在考虑将函数名称存储在文本字段中。一旦需要,你将如何运行它? ImportLib似乎很有趣......

回答

1

存储函数名是一个有效的方法,因为它实际上是pickle module使用的。这有利于(就你而言),如果你更新函数的代码,它将自动应用于现有的电子邮件(但要注意向后兼容性)。

为了方便和安全(尤其是如果函数名可能来自用户输入),您可能希望将所有这些函数保留在同一模块中,并且只将函数名称存储在数据库中,而不是完整的导入路径。所以你可以简单地导入函数库并用getattr来读取它。我想你也会想给这些函数提供参数。如果您不想将自己限制为给定数量/顺序/类型的参数,则可以将字典存储为JSON字符串,然后使用**运算符将其展开。

import my_app.func_store as store 
import json 

func = getattr(store, self.conditional) 
params = json.loads(self.conditional_params) 
if func(**params): 
    function_send_email() 
+0

不错的答案。用户不能输入任何功能或代码,电子邮件都是从代码中生成的。所以将条件函数放在生成电子邮件的位置附近非常方便。我目前有这个电子邮件应用程序的集中版本,这是一个噩梦来维护。这就是为什么我正在研究这个想法.. :-) –