2013-11-29 7 views
5

私のdjangoプロジェクトで非常に奇妙な問題に直面しています。私のプロジェクトでは、外部キー、一対一、そして多くの2つのモデルフィールドを扱うカスタムフィールドクラスがあります。クラスは以下のようなものです。Djangoデータベースのクエリを行うカスタムフィールドの属性

from django import forms 


class CustomRelatedField(forms.Field): 
    def __init__(self, model, limit=None, multiple=False, create_objects=True, *args, *kwargs): 
     self.model = model 
     self.limit = limit 
     self.multiple = multiple 
     self.create_objects = create_objects 

     super(CustomRelatedField, self).__init__(*args, **kwargs) 

    def clean(self, value): 
     """ Calls self.get_objects to get the actual model object instance(s) 
      from the given unicode value. 
     """ 
     # Do some value processing here 
     return self.get_objects(value) 

    def get_objects(self, values): 
     """ Returns the model object instances for the given unicode values. 
     """ 

     results = [] 
     for value in values: 
      try: 
       obj = self.model.object.get_or_create(name=value)[0] 
       results.append(obj) 
      except Exception, err: 
       # Log the error here. 

     return results 

    def prepare_value(self, value): 
     """ Returns the value to be sent to the UI. The value 
      passed to this method is generally the object id or 
      a list of object id's (in case it is a many to many object). 
      So we need to make a database query to get the object and 
      then return the name attribute. 
     """ 

     if self.multiple: 
      result = [obj.name for obj in self.model.filter(pk__in=value)] 
     else: 
      result = self.model.object.get(pk=value) 

     return result 

最近、私はdjango-toolbarで遊んでいた一方で、私は途方もなく何度も何度も同じオブジェクトに対して複数のクエリを作っていた上記のフィールドを持つフォームを持っているのいずれかのページを見つけました。

enter image description here

デバッグしている間、私はprepare_value方法は、何度も何度も呼ばれていたが分かりました。もう少しデバッグした後、私はその犯人がテンプレートであることに気付きました。各if文は、データベースクエリを作るprepare_valueメソッドを呼び出して、フィールドクラスを呼び出して、上記のコードで

{% for field in form %} 
    {% if field.is_hidden %} 
     <!-- Do something here --> 
    {% endif %} 

    {% if field.field.required %} 
     <!-- Do something here --> 
    {% endif %} 

    <label>{{ field.label }}</label> 
    <div class="form-field">{{ field }}</div> 

    {% if field.field.widget.attrs.help_text %} 
     <!-- Do something here --> 
    {% elif field.errors %} 
     <!-- Do something here --> 
    {% endif %} 
{% endfor %} 

:私は、それは次のようになります、私はフォームに使用する汎用テンプレートを持っています。以下のリストのそれぞれは、データベースクエリを作成していますが、なぜこれが起こっているのか、解決策について何の手がかりも全く失っています。どんな助けや提案も本当に感謝しています。ありがとう。

  • field.is_hidden
  • field.field.required
  • field.label
  • field.label_tag
  • フィールド
  • フィールド
  • field.field.widget.attrs.help_text。エラー

また、なぜt私のカスタムフィールドクラスだけで、アプリケーションとアプリケーション管理者の他のフィールド(FK、O2Os、M2M)は、同じテンプレートを使用していても、1つのクエリを作成します。

+0

あなたはどのバージョンのdjangoを使用していますか? – aquavitae

+0

Djangoバージョン - (1,5,5、 'final'、0) – Amyth

答えて

5

明示的なクエリを実行するprepare_value()メソッドで問題が発生しています。 .get()はキャッシュされず、常に反復する間にdbにヒットします。.filter() querysetはそれを評価します。 これにより、複数のクエリが発生している可能性があります。

prepare_value()でクエリを実行しないため、デフォルトのフィールドには表示されません。

これを解決するには、valueresultをキャッシュすることができます。 valueが変更されていない場合は、キャッシュされた結果を返します。次のようなものがあります。

class CustomRelatedField(forms.Field): 
    def __init__(self, model, limit=None, multiple=False, create_objects=True, *args, *kwargs): 
     self.cached_result = None 
     self.cached_value = None 
    ... 
    def prepare_value(self, value): 
     #check we have cached result 
     if value == self.cached_value: 
      return self.cached_result 

     if self.multiple: 
      result = [obj.name for obj in self.model.filter(pk__in=value)] 
     else: 
      result = self.model.object.get(pk=value) 

     #cache the result and value 
     self.cached_result = result 
     self.cached_value = value  
     return result 

どのように良いことと悪いことがわかりません!

+0

ありがとう、それは問題を修正したようです。私はこれをしばらく試してみるつもりだし、すべてが大丈夫だとすれば、賞金を授与する – elssar

関連する問題