2011-07-26 3 views
1

私はDjangoで働いています。 Djangoでは、テンプレートをレンダリングするときにコンテキストディクショナリを送信して置き換えます。私は怠惰な/ DRYなので、{'my_var':my_var、 'var2':var2}のような辞書を送るのではなく、locals()をショートカットとして使うことがよくあります。Python:地元の漬物()、または地元の人々は軽量のいとこを持っていますか?

これは通常、美しく動作し、心の麻痺の繰り返しをたくさん保存します。

私は、特定のイベントが発生したときに電子メールを送信するためにDjango通知を使用しています。 Djangoの通知には、現在組み込まれている組み込みのキュー機能が付属しています。

しかし、問題は、django-notificationsがキュー時にコンテキストディクショナリをpickleすることです。これはlocals()のトリックが失敗するところです。ローカルの辞書は、ローカル変数を超えて多くの些細なことがあります(例えば、importとint())。地元の人々によって作成された辞書は漬けません。

私はdjango-notificationsのキューイング方法を書き直して、テンプレートを保存する前にレンダリングします(簡単ですがちょっと退屈でアップグレード性が損なわれます)2)ローカルトリックの使用をやめて繰り返し始めます3)軽量版の地元住民(または地元の人を漬ける方法)を探してみてください。

私は、誰かが#3の方向にリードを持ちたいと考えています。

それは、関連するかもしれない場合は、ここで私は(地元の人々を使用して酸洗しようとすると、私が取得エラー)のショートカットです:さらに

TypeError: can't pickle ellipsis objects 

、地元の人々の辞書の出力は():

{ 
    '__builtins__': 
    { 
     'bytearray': <type 'bytearray'>, 
     'IndexError': <type 'exceptions.IndexError'>, 
     'all': <built-in function all>, 
     'help': Type help() for interactive help, 
     or help(object) for help about object., 
     'vars': <built-in function vars>, 
     'SyntaxError': <type 'exceptions.SyntaxError'>, 
     'unicode': <type 'unicode'>, 
     'UnicodeDecodeError': <type 'exceptions.UnicodeDecodeError'>, 
     'isinstance': <built-in function isinstance>, 
     'copyright': Copyright (c) 2001-2010 Python Software Foundation. 
All Rights Reserved. 

Copyright (c) 2000 BeOpen.com. 
All Rights Reserved. 

Copyright (c) 1995-2001 Corporation for National Research Initiatives. 
All Rights Reserved. 

Copyright (c) 1991-1995 Stichting Mathematisch Centrum, 
     Amsterdam. 
All Rights Reserved., 
     'NameError': <type 'exceptions.NameError'>, 
     'BytesWarning': <type 'exceptions.BytesWarning'>, 
     'dict': <type 'dict'>, 
     'input': <built-in function input>, 
     'oct': <built-in function oct>, 
     'bin': <built-in function bin>, 
     'SystemExit': <type 'exceptions.SystemExit'>, 
     'StandardError': <type 'exceptions.StandardError'>, 
     'format': <built-in function format>, 
     'repr': <built-in function repr>, 
     'sorted': <built-in function sorted>, 
     'False': False, 
     'RuntimeWarning': <type 'exceptions.RuntimeWarning'>, 
     'list': <type 'list'>, 
     'iter': <built-in function iter>, 
     'reload': <built-in function reload>, 
     'Warning': <type 'exceptions.Warning'>, 
     '__package__': None, 
     'round': <built-in function round>, 
     'dir': <built-in function dir>, 
     'cmp': <built-in function cmp>, 
     'set': <type 'set'>, 
     'bytes': <type 'str'>, 
     'reduce': <built-in function reduce>, 
     'intern': <built-in function intern>, 
     'issubclass': <built-in function issubclass>, 
     'Ellipsis': Ellipsis, 
     'EOFError': <type 'exceptions.EOFError'>, 
     'locals': <built-in function locals>, 
     'BufferError': <type 'exceptions.BufferError'>, 
     'slice': <type 'slice'>, 
     'FloatingPointError': <type 'exceptions.FloatingPointError'>, 
     'sum': <built-in function sum>, 
     'getattr': <built-in function getattr>, 
     'abs': <built-in function abs>, 
     'exit': Use exit() or Ctrl-D (i.e. EOF) to exit, 
     'print': <built-in function print>, 
     'True': True, 
     'FutureWarning': <type 'exceptions.FutureWarning'>, 
     'ImportWarning': <type 'exceptions.ImportWarning'>, 
     'None': None, 
     'hash': <built-in function hash>, 
     'ReferenceError': <type 'exceptions.ReferenceError'>, 
     'len': <built-in function len>, 
     'credits':  Thanks to CWI, 
     CNRI, 
     BeOpen.com, 
     Zope Corporation and a cast of thousands 
    for supporting Python development. See www.python.org for more information., 
     'frozenset': <type 'frozenset'>, 
     '__name__': '__builtin__', 
     'ord': <built-in function ord>, 
     'super': <type 'super'>, 
     '_': None, 
     'TypeError': <type 'exceptions.TypeError'>, 
     'license': Type license() to see the full license text, 
     'KeyboardInterrupt': <type 'exceptions.KeyboardInterrupt'>, 
     'UserWarning': <type 'exceptions.UserWarning'>, 
     'filter': <built-in function filter>, 
     'range': <built-in function range>, 
     'staticmethod': <type 'staticmethod'>, 
     'SystemError': <type 'exceptions.SystemError'>, 
     'BaseException': <type 'exceptions.BaseException'>, 
     'pow': <built-in function pow>, 
     'RuntimeError': <type 'exceptions.RuntimeError'>, 
     'float': <type 'float'>, 
     'MemoryError': <type 'exceptions.MemoryError'>, 
     'StopIteration': <type 'exceptions.StopIteration'>, 
     'globals': <built-in function globals>, 
     'divmod': <built-in function divmod>, 
     'enumerate': <type 'enumerate'>, 
     'apply': <built-in function apply>, 
     'LookupError': <type 'exceptions.LookupError'>, 
     'open': <built-in function open>, 
     'quit': Use quit() or Ctrl-D (i.e. EOF) to exit, 
     'basestring': <type 'basestring'>, 
     'UnicodeError': <type 'exceptions.UnicodeError'>, 
     'zip': <built-in function zip>, 
     'hex': <built-in function hex>, 
     'long': <type 'long'>, 
     'next': <built-in function next>, 
     'ImportError': <type 'exceptions.ImportError'>, 
     'chr': <built-in function chr>, 
     'xrange': <type 'xrange'>, 
     'type': <type 'type'>, 
     '__doc__': "Built-in functions, 
     exceptions, 
     and other objects.\n\nNoteworthy: None is the `nil' object; Ellipsis represents `...' in slices.", 
     'Exception': <type 'exceptions.Exception'>, 
     'tuple': <type 'tuple'>, 
     'UnicodeTranslateError': <type 'exceptions.UnicodeTranslateError'>, 
     'reversed': <type 'reversed'>, 
     'UnicodeEncodeError': <type 'exceptions.UnicodeEncodeError'>, 
     'IOError': <type 'exceptions.IOError'>, 
     'hasattr': <built-in function hasattr>, 
     'delattr': <built-in function delattr>, 
     'setattr': <built-in function setattr>, 
     'raw_input': <built-in function raw_input>, 
     'SyntaxWarning': <type 'exceptions.SyntaxWarning'>, 
     'compile': <built-in function compile>, 
     'ArithmeticError': <type 'exceptions.ArithmeticError'>, 
     'str': <type 'str'>, 
     'property': <type 'property'>, 
     'GeneratorExit': <type 'exceptions.GeneratorExit'>, 
     'int': <type 'int'>, 
     '__import__': <built-in function __import__>, 
     'KeyError': <type 'exceptions.KeyError'>, 
     'coerce': <built-in function coerce>, 
     'PendingDeprecationWarning': <type 'exceptions.PendingDeprecationWarning'>, 
     'file': <type 'file'>, 
     'EnvironmentError': <type 'exceptions.EnvironmentError'>, 
     'unichr': <built-in function unichr>, 
     'id': <built-in function id>, 
     'OSError': <type 'exceptions.OSError'>, 
     'DeprecationWarning': <type 'exceptions.DeprecationWarning'>, 
     'min': <built-in function min>, 
     'UnicodeWarning': <type 'exceptions.UnicodeWarning'>, 
     'execfile': <built-in function execfile>, 
     'any': <built-in function any>, 
     'complex': <type 'complex'>, 
     'bool': <type 'bool'>, 
     'ValueError': <type 'exceptions.ValueError'>, 
     'NotImplemented': NotImplemented, 
     'map': <built-in function map>, 
     'buffer': <type 'buffer'>, 
     'max': <built-in function max>, 
     'object': <type 'object'>, 
     'TabError': <type 'exceptions.TabError'>, 
     'callable': <built-in function callable>, 
     'ZeroDivisionError': <type 'exceptions.ZeroDivisionError'>, 
     'eval': <built-in function eval>, 
     '__debug__': True, 
     'IndentationError': <type 'exceptions.IndentationError'>, 
     'AssertionError': <type 'exceptions.AssertionError'>, 
     'classmethod': <type 'classmethod'>, 
     'UnboundLocalError': <type 'exceptions.UnboundLocalError'>, 
     'NotImplementedError': <type 'exceptions.NotImplementedError'>, 
     'AttributeError': <type 'exceptions.AttributeError'>, 
     'OverflowError': <type 'exceptions.OverflowError'> 
    }, 
    'notification': <module 'notification.models' from '/home/b/webapps/myapp/notification/models.pyc'>, 
    'u': <User: abcd>, 
    'User': <class 'django.contrib.auth.models.User'> 
} 
+5

あなたの問題はちょっとだけ賢いことから始まりました。あなたが何かできる(例えば、Contextのdictとして 'locals()を使用するなど)、それが良い考えであるとは限りません。あなたが明示的に述べたい値を使って直接ディクテーションを構築するには、時間がかからず、この他の「作成された」問題を完全に回避します。 [Zen of Python](http://www.python.org/dev/peps/pep-0020/)を調べて、アイテム2に注意してください。 –

+1

オブジェクトが15個ある場合、地元の人々の時間を節約できます()。神 - この反復は、たとえ重大な節約でさえも嫌にします。 – Ted

+0

ええ、でも、あなたはどれくらいの時間を浪費していますか。私が行ったすべてのDjangoサイトでは、6つ以上の値を持つビュー固有のコンテキストはほとんどありませんでした。一方、私はすべてのソートを提供する一般的な[コンテキストプロセッサ](https://docs.djangoproject.com/en/dev/ref/templates/api/#writing-your-own-context-processors)を持っています私たちのテンプレートには一般的に有用な情報があります。 –

答えて

0

いいえ、あなたがピクルスに行く場合は、自分自身を繰り返す価値があります。直感的ではないオブジェクトの多くは、ピクルすることができない(すなわち、フォーム入力)。

locals()ショートカットは、テンプレートがすぐに表示されることが確実である場合にのみ使用してください。

0

おそらくグローバルにない地方のものすべてを格納することができます。

2

私はあなたがそれらを作成すると、単にコンテキストにオブジェクトを追加することですlocals()

class Object(object): 
    pass 

def foo(): 
    result = Object() 
    result.my_var = 'bar' 
    your_var = 'not to be returned' 
    result.var2 = 'baz' + result.my_var + len(your_var) 
    return result.__dict__ 

別のオプションを使用する代わりを提案することを可能にしてください。

def foo(): 
    result = {} 
    result['my_var'] = my_var = 'bar' 
    your_var = 'not to be returned' 
    result['var2'] = var2 = 'baz' + my_var + len(your_var) 
    return result 

複数の割り当てを使用すると、変数を変更するたびに発生していることを確認します(または、少なくとも非常に最後の時間)、けれども。

編集:この2番目のバージョンを使用してください。私はコンテクスト辞書(resultまたはctxなど)を使用することの追加のキーストロークは非常にドライではないと確信していますが、これは実際には良いことです。 Pythonの禅ではが "明示的に暗黙的に優れている"と述べています。locals()の値を返すと、誰が何を知っているかを返します。グローバルな名前空間にあったもの、ネストされた名前空間にあるもの、中間的な計算のすべてが、暗黙のうちに呼び出し元に返されます。

あなたは、あなたが、明示的にあなたの意図を作る

this_is_for_me = 'foo' 

result['this_is_for_you'] = 'bar' 

差とシャープなラインを描いている戻したい値用のコンテナを作成した場合では明らかです何が公開されているのか、ほかの人が使用するのをコードする。プライベート、変更の対象となる、実装固有。これらのプライベートな値は単純に利用できないので、呼び出し元にも明らかです。

そして、決して無駄のない外部ライブラリを統合する場合は、どこでどのように使用するかを非常に気にする必要があります。私はおそらくパッチ他のオプションよりもこれを行うコードを好むでしょう。

+0

さらに簡単には、コンテキストdictに直接書き込みます(つまり、ローカルの 'a'を使用する場合はどこでも' ctx ['a'] '代わりに)。 –

+0

私は原則的にプレーンテキストの使用を計画していましたが、ポスターが3つの余分な文字、result.my_varの代わりにresult ['my_var'] 'をタイプしなければならないことに反対していると思います。はい、私は本当に普通の言葉だけを使うのが好きです。 – SingleNegationElimination

+0

これは良い解決策ですが、djangoのコンテキストでは、オブジェクトです。変数は実際には動作しないコミュニティ標準ではありません。それは、私がコミュニティアプリを引っ張ると、ローカルオブジェクトにローカル変数を格納するためのすべての関数をやり直す必要があることを意味します。これは私にはこれを非スターターにします。 – Ted

0

あなたのコードスニペットにはlocals()からのものは表示されませんが、それはdillで「un-pickleable」です。 DillはPythonのほとんどすべてをシリアライズすることができます。また、コードが失敗したときに酸洗が失敗する原因を理解するためのsome good toolsもあります。限りdjangopickleなくcPickleを使用すると、あなたがEllipsisTypeのようなものをシリアル化するためにピクルスを拡張するためにしなければならないすべては、次のとおりです。

>>> import dill 
>>> # this will enable python's pickle to pickle almost everything dill can pickle 
>>> 
>>> # on the full set of dill's types, this usually works unless there's a generator 
>>> # or an interator-type or something odd like a traceback object in locals 
>>> dill.loads(dill.dumps(locals())) 
>>> ... 
>>> # if you get a pickling error, use dill's tools to figure out a workaround 
>>> dill.detect.badobjects(your_bad_object, depth=0) 
>>> dill.detect.badobjects(your_bad_object, depth=1) 
>>> ... 

あなたは絶対にしたい場合、あなたはディルのbadobjects(または他のいずれかを使用することができます検出機能)を使用して、locals()参照チェーン内のすべてに再帰的に潜入し、上記のようにすべての深度で呼び出すのではなく、unpickleableオブジェクトをポップアウトします。

関連する問題