2013-11-29 25 views
5

Django projelerimden birinde çok garip bir sorunla karşı karşıyayım. Projemde, yabancı anahtarları, bire bir ve birçok 2 model alanını ele alan özel bir alan sınıfına sahibim. Sınıf, aşağıdaki gibi bir şeydir.Django Özel alanın özniteliklerini veritabanı sorguları yapma

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 

Son zamanlarda django-toolbar ile oynarken, ben gülünç tekrar tekrar aynı nesneler için birden fazla sorgu yapıyordu yukarıda belirtilen alanlar ile bir form vardır sayfalarından birini öğrendim.

enter image description here

ayıklama iken, prepare_value yöntemi tekrar çağrılan öğrenmiş. Daha fazla hata ayıklamasından sonra, suçlunun şablon olduğunu anladım. Her if deyimi sonra veritabanı sorgularını yapan prepare_value yöntemini çağıran alan sınıf çağıran, yukarıdaki kodda

{% 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 %} 

: Ben Aşağıdaki gibi görünür, ben formlar için kullanmak genel bir şablon var. Aşağıda listelenen her biri bir veritabanı sorgusu yapıyor, bunun neden olduğu konusunda tamamen kayıyorum ve herhangi bir çözüm hakkında hiçbir fikrim yok. Herhangi bir yardım, öneri gerçekten takdir edilecektir. Teşekkürler.

  • field.is_hidden
  • field.field.required
  • field.label
  • field.label_tag
  • alan
  • field.field.widget.attrs.help_text
  • alanı. hatalar

Ayrıca, neden Onun sadece benim özel alan sınıfı ile, uygulamadaki diğer alanlar (FKs, O2Os, M2M'ler) ve uygulama yöneticisi, sadece benzer bir şablon kullansalar bile, sadece bir sorgu yapın.

+0

Django'nun hangi sürümünü kullanıyorsunuz? – aquavitae

+0

Django Sürümü - (1, 5, 5, 'final', 0) – Amyth

cevap

5

Sorunun cevabı açık olan prepare_value() yönteminizle doludur. .get() önbelleğe alınmaz ve her zaman 0bqueryset üzerinde yineleme yaparken db vurur. Bu, birden çok soruna neden olabilir.

Bu, prepare_value() içinde herhangi bir sorgulama yapmadıklarından, varsayılan alanlarda görülmez.

Bu sorunu çözmek için, value ve result önbelleğe deneyebilirsiniz. value değişmemişse, önbelleğe alınan sonucu döndürün. Şunlar gibi:

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 

Bunun ne kadar iyi/kötü çalıştığından emin değilsiniz!

+0

Teşekkürler, bu sorunu çözmüş görünüyor. Bunu bir süreliğine test edeceğim ve her şey yolunda giderse, sana ödül vereceğim – elssar

İlgili konular