一种方法是创建一个管理器并使用原始 SQL 查询定义一个函数。创建模型对象,将新的计算字段引用到 self.model 的模型类
Class MyModel(models.Model):
fieldA = models.FloatField()
fieldB = models.FloatField()
objects = MyModelManager() #Binds the manager to the model
Class MyModelManager(models.Manager):
def ReturnDelta(self):
from django.db import connection
cursor = connection.cursor()
cursor.execute = """SELECT fieldA, fieldB, fieldA-fieldB as delta
from MyModel_table"""
result_list = []
for row in cursor.fetchall():
p = self.model(fieldA=row[0], fieldB[1]) #access the model associated w/ the manager
p.delta = row[2] #adds the new field to the queryset
result_list.append(p)
return result_list
几乎是来自Django Documentation的复制粘贴
然后我们可以使用通用视图的额外上下文字典中的管理器功能。并进行代数运算而不会不必要地访问数据库。
更好的解决方案是使用自定义管理器创建您自己的 QuerySet 类。这允许链接过滤器并将任何计算值作为 QuerySet 属性返回。几乎是直接取自这个snippet
class CustomManager(models.Manager):
'''
An general purpose manager which allows to filter a queryset
and chain filters
"Constructor": CustomManager(CustomQuerySetClass)
'''
def __init__(self, qs_class=models.query.QuerySet):
super(CustomManager,self).__init__()
self.queryset_class = qs_class
def get_query_set(self):
return self.queryset_class(self.model)
def __getattr__(self, attr, *args):
try:
return getattr(self.__class__, attr, *args)
except AttributeError:
return getattr(self.get_query_set(), attr, *args)
class MyModelQuerySet(models.query.QuerySet):
'''
A very specific queryset designed to return a computed value (this
time a sum of all rows values)
'''
def filter(self, *args, **kwargs):
qs = super(MyModelQuerySet, self).filter(*args,**kwargs)
sum=0
for row in qs:
sum += row.delta #use a callback to prevent from caching
setattr(qs, 'sum',sum)
return qs
class MyModel(models.Model):
objects = CustomManager() #Binds the manager to the model
fieldA = models.FloatField()
fieldB = models.FloatField()
def delta(self):
return self.fieldA - self.fieldB