2013-11-29 19 views
5

Tôi đang đối mặt với một vấn đề rất lạ trong một trong các dự án django của tôi. Trong dự án của tôi, tôi có một lớp trường tùy chỉnh xử lý các khóa ngoài, một đến một và nhiều trường mô hình 2 nhiều. Lớp học là một số thứ như sau.Thuộc tính của trường tùy chỉnh Django tạo truy vấn cơ sở dữ liệu

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 

Gần đây trong khi tôi đang chơi với django-toolbar, tôi phát hiện ra một trong những trang mà có một mẫu với các lĩnh vực nêu trên được ridiculously làm nhiều truy vấn cho các đối tượng tương tự một lần nữa và một lần nữa.

enter image description here

Trong khi gỡ lỗi, tôi phát hiện ra phương pháp prepare_value đã được gọi là một lần nữa và một lần nữa. Sau khi một số gỡ lỗi nhiều hơn, tôi nhận ra thủ phạm là mẫu. Tôi có một mẫu chung mà tôi sử dụng cho các hình thức, Nó trông giống như sau:

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

Trong đoạn mã trên, mỗi câu lệnh if gọi là lớp lĩnh vực mà các cuộc gọi prepare_value phương pháp mà sau đó làm cho các truy vấn cơ sở dữ liệu. Mỗi một trong những điều sau đây được liệt kê là tạo truy vấn cơ sở dữ liệu, tôi hoàn toàn mất đi lý do tại sao điều này xảy ra và không có đầu mối về bất kỳ giải pháp nào. Bất kỳ trợ giúp, đề xuất sẽ được thực sự đánh giá cao. Cảm ơn.

  • field.is_hidden
  • field.field.required
  • field.label
  • field.label_tag
  • lĩnh vực
  • field.field.widget.attrs.help_text
  • lĩnh vực. lỗi

Ngoài ra, tại sao t sự kiện của anh ta chỉ xảy ra với lớp tùy chỉnh của tôi, các trường khác (FK, O2O, M2M) trong ứng dụng và quản trị viên ứng dụng, chỉ cần thực hiện một truy vấn, mặc dù chúng đang sử dụng một khuôn mẫu tương tự.

+0

Bạn đang sử dụng phiên bản django nào? – aquavitae

+0

Phiên bản Django - (1, 5, 5, 'cuối cùng', 0) – Amyth

Trả lời

5

Vấn đề với phương pháp prepare_value() của bạn có truy vấn rõ ràng. .get() không được lưu trong bộ nhớ cache và luôn truy cập db trong khi lặp lại trên .filter() bộ truy vấn sẽ đánh giá điều đó. Điều này có thể khiến bạn có nhiều truy vấn.

Điều này không được hiển thị trong các trường mặc định vì chúng không thực hiện bất kỳ truy vấn nào trong prepare_value().

Để giải quyết vấn đề này, bạn có thể thử lưu vào bộ nhớ cache valueresult. Nếu value chưa thay đổi, hãy trả lại kết quả được lưu trong bộ nhớ cache. Một cái gì đó như:

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 

Không chắc chắn cách tốt/xấu này hoạt động xung quanh!

+0

Cảm ơn, điều đó dường như đã khắc phục được sự cố. Tôi sẽ kiểm tra điều này trong một thời gian và nếu tất cả có vẻ ổn, sẽ trao cho bạn tiền thưởng – elssar

Các vấn đề liên quan