避免进行多个Django数据库调用

时间:2020-06-19 13:27:12

标签: python sql django database loops

我想查询我的Django数据库一次并返回一个Queryset(分配给代码“ codes”),我可以对其进行迭代以获取每个实例的“ internal_code”属性,而无需进一步调用数据库。这是我的代码,但是我不确定每次我在Queryset上使用'get'时是否要查询数据库,以及如何避免这种情况:

codes = models.RecordType.objects.all()

permanent = sorted([
    (
        codes.get(
            industry_code=category.value
        ).internal_code,
        self.labels.get(category, category.name)
    )
    for category in enums.Category
])

3 个答案:

答案 0 :(得分:0)

如果要强制评估QuerySet,可以执行以下操作:

codes = list(models.RecordType.objects.all())

答案 1 :(得分:0)

使用__in运算符对{{1}枚举中存在filter的所有RecordType industry_code

Category

如果codes = ( RecordType.objects .filter(industry_code__in=[c.value for c in Category]) .only('industry_code', 'internal_code') ) category_labels = {c.value: self.labels.get(c, c.name) for c in Category} permanent = sorted([ (code.internal_code, category_labels[code.industry_code]) for code in codes ]) 有很多不需要的字段,请使用.only

但是我不确定每次查询集上使用'get'时是否查询数据库

是的。您可以链接RecordType.filter()和其他返回查询集而不运行查询集的方法。使用.exclude()可以立即(且每次)评估查询集,并返回一个实例。

答案 2 :(得分:0)

您编写的内容大致是这样做的方法,但是您不应该一直在它上调用get()。每次执行此操作时,您都在进行单独的数据库查询。

当您指示需要结果时,Django会从数据库中延迟获取。例如

# first enable some logging to see the database queries
import logging.config
logging.config.dictConfig({
    'version': 1,
    'formatters': {
        'simple': {'format': '%(levelname)s %(message)s'},
    },
    'handlers': {
        'console': {
            'level': 'DEBUG',
            'class': 'logging.StreamHandler',
            'formatter': 'simple',
        },
    },
    'root': {
        'level': 'WARNING',
        'handlers': ['console'],
    },
    'loggers': {
        'django.db.backends': {'level': 'DEBUG',},
    },
})


# No query made
codes = RecordType.objects.filter(
    industry_code__in=[cat.value for cat in enums.Category]
)

# show the query that will be made (roughly)
print(str(codes.query))

# force the queryset to be executed and return all the results.
# the queryset is executed when you iterate over it.
codes_by_industry_code = {
    code.industry_code: code
    for code in codes
}

# now you can set up your list:
permanent = [
    (
        codes_by_industry_code[category.value].internal_code,
        self.labels.get(category, category.name)
    )
    for category in enums.Category
]

现在,如果要确保查询仅在正确的位置进行,则应使用this question中所述的测试工具来测试代码。这是确保继续执行您的代码按照数据库查询应做的唯一方法。

相关问题