【问题标题】:Matching fields in different tables in DjangoDjango中不同表中的匹配字段
【发布时间】:2014-06-30 07:05:28
【问题描述】:

我有两个完全不相关的 Django 模型。像这样的:

class OldModel(models.Model):
    name = models.CharField(max_length=100)

class NewModel(models.Model):
    name = models.CharField(max_length=100)

它们都包含大量记录。我只想从NewModel 中过滤掉那些名称等于OldModel 中某些记录的记录。使用 Django ORM 最快、最有效的方法是什么?

【问题讨论】:

    标签: python django django-models orm


    【解决方案1】:

    new_models = NewModel.objects.filter( name__in=OldModel.objects.all().values_list('name', flat=True) )

    这将导致对数据库的折叠选择查询。要查看原始 sql 查询,只需键入 print new_models.query

    【讨论】:

    • 这似乎是最有效的方法。现在,我想知道如何为同一个查询打印两个模型的名称?
    【解决方案2】:

    我只能考虑使用平面值列表调用 name__in 查找。

    old_models = OldModel.objects.all()
    old_model_names = old_models.values_list('name', flat=True)
    new_models = NewModel.objects.filter(name__in=old_model_names)
    

    这应该转换成这样的 SQL 查询

    SELECT * FROM newmodel WHERE name in (SELECT name from oldmodel);
    

    您也可以考虑extra 语句,它允许创建优化版本的查询

    请在此处查看文档

    https://docs.djangoproject.com/en/dev/ref/models/querysets/#django.db.models.query.QuerySet.extra

    您应该使用where / tables 的一部分。但这确实不是原始的 Django ORM。

    如需更准确的 SQL 查询,请使用来自 OldModel._metaNewModel._meta 的信息,这将允许您不对字段和表名称进行硬编码。

    【讨论】:

    • 不能有更高效的方法吗?因为old_models = OldModel.objects.all() 将在评估为:SELECT * FROM old_models 时停止一切。这是我想避免的。
    • 这不会发生,因为查询集是惰性的。仅在需要时才对它们进行评估(针对数据库执行)。查询集将在filter 中进行评估,在那里它将作为“SELECT name FROM ...”执行
    • 但是old_model_names = old_models.values_list('name', flat=True) 会导致查询执行,不是吗?这将评估为SELECT * FROM table_name,对吗?
    • 这不会发生,因为查询集是惰性的。 '不能有更有效的方法吗?' 第二个 extra 更有效
    猜你喜欢
    • 2018-08-14
    • 2013-08-15
    • 1970-01-01
    • 2020-08-19
    • 2013-02-18
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2018-07-11
    相关资源
    最近更新 更多