按属性过滤

2025-02-10 08:57:00
admin
原创
55
摘要:问题描述:是否可以通过模型属性过滤 Django 查询集?我的模型中有一个方法:@property def myproperty(self): [..] 现在我想通过这个属性进行过滤,例如:MyModel.objects.filter(myproperty=[..]) 这可能吗?解决方案 1:不是。D...

问题描述:

是否可以通过模型属性过滤 Django 查询集?

我的模型中有一个方法:

@property
def myproperty(self):
    [..]

现在我想通过这个属性进行过滤,例如:

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

这可能吗?


解决方案 1:

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

解决方案 2:

我可能误解了你最初的问题,但是python 中有一个内置过滤器。

filtered = filter(myproperty, MyModel.objects)

但最好使用列表推导:

filtered = [x for x in MyModel.objects if x.myproperty()]

甚至更好,一个生成器表达式:

filtered = (x for x in MyModel.objects if x.myproperty())

解决方案 3:

借鉴@TheGrimmScientist 建议的解决方法,您可以通过在 Manager 或 QuerySet 上定义这些“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()

更多信息请参阅https://docs.djangoproject.com/en/1.9/topics/db/managers/。请注意,我没有参考文档,也没有测试上述内容。

解决方案 4:

看起来使用带有注释的 F()将是我的解决方案。

它不会按 进行过滤@property,因为F在将对象带入 python 之前会与数据库进行对话。但仍然将其作为答案放在这里,因为我想要按属性进行过滤的原因实际上是想根据两个不同字段的简单算术结果来过滤对象。

因此,大致如下:

companies = Company.objects\n    .annotate(chairs_needed=F('num_employees') - F('num_chairs'))\n    .filter(chairs_needed__lt=4)

而不是将属性定义为:

@property
def chairs_needed(self):
    return self.num_employees - self.num_chairs

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

解决方案 5:

我遇到了同样的问题,并且我开发了这个简单的解决方案:

objects = [
    my_object 
    for my_object in MyModel.objects.all() 
    if my_object.myProperty == [...]
]

这不是一个高性能的解决方案,它不应该在包含大量数据的表中完成。这对于简单的解决方案或个人小项目来说很棒。

解决方案 6:

请有人纠正我,但我想我已经找到了解决方案,至少对我自己的情况而言。

我想要研究所有那些属性完全等于...无论什么的元素。

但是我有多个模型,这个例程应该适用于所有模型。并且它确实如此:

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)

使用这个通用子程序,我可以选择所有与我的“指定”(属性名称,属性值)组合词典完全相等的元素。

第一个参数采用(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 

然后呢?你觉得怎么样?

解决方案 7:

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

如何在 Django 1.4 中自定义管理过滤器

解决方案 8:

还可以使用重复属性 get/set-logic 的查询集注释,例如@rattray和@thegrimmscientist所建议的,与 结合使用property这可以产生在 Python 级别数据库级别都有效的东西。

但不确定其缺点:请参阅这个 SO 问题作为示例。

相关推荐
  政府信创国产化的10大政策解读一、信创国产化的背景与意义信创国产化,即信息技术应用创新国产化,是当前中国信息技术领域的一个重要发展方向。其核心在于通过自主研发和创新,实现信息技术应用的自主可控,减少对外部技术的依赖,并规避潜在的技术制裁和风险。随着全球信息技术竞争的加剧,以及某些国家对中国在科技领域的打压,信创国产化显...
工程项目管理   1565  
  为什么项目管理通常仍然耗时且低效?您是否还在反复更新电子表格、淹没在便利贴中并参加每周更新会议?这确实是耗费时间和精力。借助软件工具的帮助,您可以一目了然地全面了解您的项目。如今,国内外有足够多优秀的项目管理软件可以帮助您掌控每个项目。什么是项目管理软件?项目管理软件是广泛行业用于项目规划、资源分配和调度的软件。它使项...
项目管理软件   1354  
  信创国产芯片作为信息技术创新的核心领域,对于推动国家自主可控生态建设具有至关重要的意义。在全球科技竞争日益激烈的背景下,实现信息技术的自主可控,摆脱对国外技术的依赖,已成为保障国家信息安全和产业可持续发展的关键。国产芯片作为信创产业的基石,其发展水平直接影响着整个信创生态的构建与完善。通过不断提升国产芯片的技术实力、产...
国产信创系统   21  
  信创生态建设旨在实现信息技术领域的自主创新和安全可控,涵盖了从硬件到软件的全产业链。随着数字化转型的加速,信创生态建设的重要性日益凸显,它不仅关乎国家的信息安全,更是推动产业升级和经济高质量发展的关键力量。然而,在推进信创生态建设的过程中,面临着诸多复杂且严峻的挑战,需要深入剖析并寻找切实可行的解决方案。技术创新难题技...
信创操作系统   27  
  信创产业作为国家信息技术创新发展的重要领域,对于保障国家信息安全、推动产业升级具有关键意义。而国产芯片作为信创产业的核心基石,其研发进展备受关注。在信创国产芯片的研发征程中,面临着诸多复杂且艰巨的难点,这些难点犹如一道道关卡,阻碍着国产芯片的快速发展。然而,科研人员和相关企业并未退缩,积极探索并提出了一系列切实可行的解...
国产化替代产品目录   28  
热门文章
项目管理软件有哪些?
云禅道AD
禅道项目管理软件

云端的项目管理软件

尊享禅道项目软件收费版功能

无需维护,随时随地协同办公

内置subversion和git源码管理

每天备份,随时转为私有部署

免费试用