Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/django/19.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Python 按属性筛选_Python_Django_Orm - Fatal编程技术网

Python 按属性筛选

Python 按属性筛选,python,django,orm,Python,Django,Orm,是否可以按模型属性筛选Django查询集 我的模型中有一个方法: @property def myproperty(self): [..] 现在我想通过这个属性进行过滤,比如: MyModel.objects.filter(myproperty=[..]) 这有可能吗?没有。Django过滤器在数据库级别运行,生成SQL。要基于Python属性进行过滤,您必须将对象加载到Python中以评估属性——此时,您已经完成了加载该对象的所有工作。我可能误解了您最初的问题,但Python中有一

是否可以按模型属性筛选Django查询集

我的模型中有一个方法:

@property
def myproperty(self):
    [..]
现在我想通过这个属性进行过滤,比如:

MyModel.objects.filter(myproperty=[..])

这有可能吗?

没有。Django过滤器在数据库级别运行,生成SQL。要基于Python属性进行过滤,您必须将对象加载到Python中以评估属性——此时,您已经完成了加载该对象的所有工作。

我可能误解了您最初的问题,但Python中有一个内置项

filtered = filter(myproperty, MyModel.objects)
但最好使用:

或者更好,a:


我知道这是一个古老的问题,但为了那些在这里跳跃的人,我认为阅读下面的问题和相关答案是有用的:


请有人纠正我,但我想我已经找到了一个解决办法,至少对我自己来说是这样

我想处理那些属性完全等于。。。不管怎样

但是我有几个模型,这个例程应该适用于所有模型。它确实:

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)
有了这个通用子例程,我可以选择所有与我的“specify”(propertyname,propertyvalue)组合字典完全相同的元素

第一个参数取a(models.Model)

第二本词典类似于: {“财产1”:“77”,“财产2”:“12”}

它创建了一个SQL语句,如

SELECT * from appname_modelname WHERE property1 = '77' AND property2 = '12'
并返回这些元素的查询集

这是一个测试功能:

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 
然后呢?你觉得呢?

看来我会解决这个问题

它不会按
@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

然后对所有对象进行列表理解。

根据@TheGrimmScientist建议的解决方法,您可以通过在管理器或查询集上定义这些“sql属性”来创建这些“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)
使用查询集:

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()
更多信息,请参阅。
请注意,我没有使用文档,也没有测试上述内容

也可以使用queryset注释来复制属性get/set逻辑,如建议的那样,
属性结合使用。这可能会产生一些在Python级别和数据库级别都有效的东西


但是,不确定缺点:请参见示例。

我也有同样的问题,我开发了这个简单的解决方案:

objects_id = [x.id for x in MyModel.objects.all() if x.myProperty == [...]]
MyModel.objects.filter(id__in=objects_id)

我知道这不是性能最好的解决方案,但在像我这样的简单情况下可能会有所帮助

不幸的是,这个功能没有实现,这将是一个有趣的扩展,至少可以在生成结果集后过滤掉匹配的对象。如何在管理中处理它?有什么解决方法吗?一旦你有了Python对象,就可以对它进行过滤,但是他问的是Django QuerySet.filter,它构造SQL queries.right,但是如上所述,我想将该属性添加到我的数据库过滤器中。查询完成后进行过滤正是我想要避免的。没有括号的x.myproperty位于SQLAlchemy中:您可以通过将django与SQLAlchemy连接起来,但我怀疑这两者是否可以按您希望的方式连接。对于浏览此答案的人,此链接是关于在Django管理员使用“SimpleListFilter”。有用,但不是问题的答案,除非是在一个非常具体的情况下。一般来说,这似乎是一个体面的工作。我不认为这是理想的,但这比每次需要这样的东西时都必须使用存储库来修改从PyPI安装的包的模型要好得多。现在我已经有时间使用它了:这种方法的真正缺点是.raw()返回的查询集不是完全成熟的查询集,我的意思是缺少queryset方法:
AttributeError:“RawQuerySet”对象没有属性“值”
您的代码审阅问题链接会通知您它是由作者自愿删除的。您是否介意在这里更新您的答案,或者添加代码链接或解释,或者删除您的答案?@hlongmore:很抱歉。这个问题被移到了这样的地步。我修复了上面的链接。
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()
objects_id = [x.id for x in MyModel.objects.all() if x.myProperty == [...]]
MyModel.objects.filter(id__in=objects_id)