Избегайте многократных обращений к базе данных Django - PullRequest
0 голосов
/ 19 июня 2020
• 1000 Вот мой код, но я не уверен, запрашиваю ли я базу данных каждый раз, когда использую «get» в Queryset, и как этого избежать:
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 голосов
/ 19 июня 2020

Использование оператора __ in для 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 в случае, если RecordType имеет много полей, которые вам не нужны.

, но я не уверен, запрашиваю ли я базу данных каждый раз, когда использую 'get' в Queryset

Да. Вы можете связать .filter(), .exclude() и другие методы, которые возвращают набор запросов, не выполняя его; с .get() набор запросов оценивается немедленно (и каждый раз), возвращая экземпляр.

0 голосов
/ 19 июня 2020

То, что вы написали, примерно соответствует тому, как это сделать, но вы не должны постоянно звонить по номеру 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
]

Теперь, если вы хотите быть уверены, что запросы выполняются только в нужном месте, вы должны использовать инструмент тестирования, такой как описанный в этот вопрос , чтобы проверить свой код. . Это единственный способ быть уверенным в том, что в будущем ваш код делает то, что должен быть с точки зрения запросов к базе данных.

0 голосов
/ 19 июня 2020

Если вы хотите принудительно выполнить оценку QuerySet, вы можете сделать это:

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

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...