2016-05-11 6 views
1

私はDjangoモデルで関数を格納する方法を探しています。 私のユースケースは、計画され、条件付きで送信されるメールシステムです。Django、データベースに関数を格納

「Johnがログインしていない場合は明日このメールを送信してください」

理想的には、テスト機能フィールドを使用して電子メールを作成したいと考えています。ここで

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で使用されているので、関数名の格納は有効なものです。これは、関数のコードを更新すると、既存の電子メールに自動的に適用されます(ただし、下位互換性には注意してください)。

利便性と安全性(特に、関数名がユーザー入力から来る可能性がある場合)では、そのような関数をすべて同じモジュールに保存し、完全なインポートパスではなく関数名のみをDBに格納することができます。したがって、単にファンクションリポジトリをインポートし、getattrで読むことができます。私は、これらの関数にパラメータを渡したがっていると思います。指定した数/型/引数の型に制限したくない場合は、DBに辞書を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

ニースの回答。ユーザーは機能やコードを入力できません。電子メールはすべてコード内から生成されます。条件関数を電子メールが生成される場所の近くに置くことは非常に便利です。私は現在、維持する悪夢であるこの電子メールアプリケーションの集中版を持っています。だからこそ私はこのアイディアに取り組んでいます:-) –

関連する問題