是否可以按屬性篩選?按屬性篩選
我有一個方法,在我的模型:
@property
def myproperty(self):
[..]
,現在我想通過這個屬性就像過濾:
MyModel.objects.filter(myproperty=[..])
是這個莫名其妙可能嗎?
是否可以按屬性篩選?按屬性篩選
我有一個方法,在我的模型:
@property
def myproperty(self):
[..]
,現在我想通過這個屬性就像過濾:
MyModel.objects.filter(myproperty=[..])
是這個莫名其妙可能嗎?
我可能會誤解你的原始問題,但python中有一個filter內建函數。
filtered = filter(myproperty, MyModel.objects)
但最好使用list comprehension:
filtered = [x for x in MyModel.objects if x.myproperty()]
,甚至更好,一個generator expression:
filtered = (x for x in MyModel.objects if x.myproperty())
我知道這是一個老問題,但對於那些着想在這裏跳我認爲這是有益的閱讀下面的問題和相關答案:
請有人糾正我,但我想我已經找到了解決方案,至少對我自己的情況。
我想處理所有這些元素的屬性完全等於......任何。
但我有幾個模型,這個例程應該適用於所有模型。它的作用:
def selectByProperties(modelType, specify):
clause = "SELECT * from %s" % modelType._meta.db_table
if len(specify) > 0:
clause += " WHERE "
for field, eqvalue in specify.items():
clause += "%s = '%s' AND " % (field, eqvalue)
clause = clause [:-5] # remove last AND
print clause
return modelType.objects.raw(clause)
這款通用子程序,我可以選擇所有那些正好等於我的「指定」(PROPERTYNAME,的PropertyValue)組合字典元素。
第一個參數需要(models.Model)
第二字典等: { 「property1」: 「77」, 「property2」: 「12」}
並創建SQL語句像
SELECT * from appname_modelname WHERE property1 = '77' AND property2 = '12'
,並返回這些元素一個QuerySet。
這是一個測試功能:
from myApp.models import myModel
def testSelectByProperties():
specify = {"property1" : "77" , "property2" : "12"}
subset = selectByProperties(myModel, specify)
nameField = "property0"
## checking if that is what I expected:
for i in subset:
print i.__dict__[nameField],
for j in specify.keys():
print i.__dict__[j],
print
還有呢?你怎麼看?
看起來像using F() with annotations將是我的解決方案。
它不會過濾@property
,因爲F
在將對象帶入python之前與數據庫進行通信。但仍然把它放在這裏作爲一個答案,因爲我希望按屬性過濾的原因是真的想通過在兩個不同的字段上進行簡單算術的結果過濾對象。
因此,沿着線的東西:
companies = Company.objects\
.annotate(chairs_needed=F('num_employees') - F('num_chairs'))\
.filter(chairs_needed__lt=4)
,而不是定義的屬性爲:
@property
def chairs_needed(self):
return self.num_employees - self.num_chairs
然後做所有的對象列表理解。
Riffing關@ TheGrimmScientist建議的解決方法,你可以通過定義他們的經理或查詢集,和複用/鏈讓這些「SQL屬性」 /撰寫他們:
隨着經理:
class CompanyManager(models.Manager):
def with_chairs_needed(self):
return self.annotate(chairs_needed=F('num_employees') - F('num_chairs'))
class Company(models.Model):
# ...
objects = CompanyManager()
Company.objects.with_chairs_needed().filter(chairs_needed__lt=4)
有了一個QuerySet:
class CompanyQuerySet(models.QuerySet):
def many_employees(self, n=50):
return self.filter(num_employees__gte=n)
def needs_fewer_chairs_than(self, n=5):
return self.with_chairs_needed().filter(chairs_needed__lt=n)
def with_chairs_needed(self):
return self.annotate(chairs_needed=F('num_employees') - F('num_chairs'))
class Company(models.Model):
# ...
objects = CompanyQuerySet.as_manager()
Company.objects.needs_fewer_chairs_than(4).many_employees()
更多見https://docs.djangoproject.com/en/1.9/topics/db/managers/。 請注意,我正在關閉文檔,並沒有測試上述內容。
它在SQLAlchemy中:http://docs.sqlalchemy.org/en/latest/orm/extensions/hybrid.html,您可以通過https://pypi.python.org/pypi/aldjemy將django與SQLAlchemy連接起來但我懷疑這兩者可以按照你希望的方式進行連接。 – rattray 2016-05-03 06:28:59