Database Django自定义字段';属性进行数据库查询

Database Django自定义字段';属性进行数据库查询,database,django,custom-fields,Database,Django,Custom Fields,在我的django项目中,我面临着一个非常奇怪的问题。在我的项目中,我有一个自定义字段类,它处理外键、一对一和多个2多模型字段。这门课是这样的 from django import forms class CustomRelatedField(forms.Field): def __init__(self, model, limit=None, multiple=False, create_objects=True, *args, *kwargs): self.m

在我的django项目中,我面临着一个非常奇怪的问题。在我的项目中,我有一个自定义字段类,它处理外键、一对一和多个2多模型字段。这门课是这样的

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
最近,当我在玩的时候,我发现其中一个页面有一个带有上述字段的表单,它一次又一次地对同一个对象进行多个查询,这很可笑

调试时,我发现
prepare\u 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 %}
{%用于表单%]中的字段
{%if field.is_hidden%}
{%endif%}
{%if field.field.required%}
{%endif%}
{{field.label}
{{field}}
{%if field.field.widget.attrs.help_text%}
{%elif field.errors%}
{%endif%}
{%endfor%}
在上面的代码中,每个
if
语句调用field类,该类调用
prepare\u value
方法,然后该方法进行数据库查询。下面列出的每个人都在进行数据库查询,我完全不明白为什么会发生这种情况,也不知道有什么解决方案。任何帮助、建议都将不胜感激。谢谢

  • 字段“”是否隐藏
  • field.field.required
  • 字段标签
  • field.label_标记
  • field.field.widget.attrs.help\u文本
  • 字段错误

另外,为什么只有我的自定义字段类会发生这种情况,应用程序中的其他字段(FKs、O2Os、M2M)和应用程序管理员只进行一次查询,即使它们使用的是类似的模板。

问题在于执行显式查询的
prepare_value()
方法
.get()
不会被缓存,在
上迭代时总是命中数据库。filter()
queryset将对此进行评估。 这可能会导致多个查询

这在默认字段中看不到,因为它们不在
prepare\u 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

但不确定这有多好/坏

您使用的是什么版本的django?django版本-(1,5,5,'final',0)谢谢,这似乎已经解决了问题。我要测试一下,如果一切正常,我会给你赏金的