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

2024-04-26 22:49:36 发布

您现在位置:Python中文网/ 问答频道 /正文

我想查询我的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
])

Tags: django实例代码名称数据库get属性models
3条回答

使用__in运算符filterCategory枚举中存在industry_code的所有RecordType

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
])

在案例RecordType中使用.only有许多您不需要的字段

but I am unsure as to whether I am querying the database each time I use 'get' on the Queryset

对。您可以链接.filter().exclude()和其他返回查询集而不运行查询集的方法;使用.get()立即(并且每次)计算queryset,返回一个实例

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

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

你写的东西大致上就是这样做的,但是你不应该总是在上面调用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中描述的测试工具来测试代码。这是确保代码按照db查询的方式运行的唯一方法

相关问题 更多 >