@DarkiDeuce

Как оптимизировать запрос к БД в цикле?

Как оптимизировать запрос к БД? Объясню логику: есть модель в которой находяться поля: логин пользователя (это поле имеет связь с моделью user, где находятся все пользователи) и несколько полей с показателями этого пользователя. Данные для заполнения БД парсятся отдельной функцией из xlsx файла, функция возвращает список словарей, где ключ это название показателя, а значение сам показатель. После этого в цикле формируется другой список, в который вносятся значения с последующим сохранением в БД.

Проблема в том, что при каждой итерации происходит обращение к БД для получения объекта логина пользователя. Из-за чего выполнение занимает очень много времени.

Предполагаю, что процесс можно оптимизировать так: сначала получить все логины пользователя, а потом, при формировании списка для сохранения в БД брать логины из уже полученного запроса. Однако не совсем понимаю как это сделать.

Функция которая парсит файл:
import openpyxl

class ImportFile:
    def __init__(self, filename, type="xlsx"):
        self.filename = filename
        self.type = type
        self.wb = None

        if self.type == "xlsx":
            self.wb = openpyxl.load_workbook(filename=filename, data_only=True)

    def import_file_kpi_base_normative(self, **kwargs):
        """Парсит файл 'КПЭ Базовый норматив'"""

        if self.wb is None:
            return []

        ws = self.wb["Лист1"]
        max_row = ws.max_row + 1

        data_for_return = []
        start_line = 4

        for row in range(start_line, max_row):
            _row = ws[row]

            data_for_return.append(
                {
                    "login": _row[10].value,
                    "plan_KVC": _row[17].value,
                    "fact_KVC": _row[21].value,
                    "plan_FZ_PU": _row[24].value,
                    "fact_FZ_PU": _row[25].value,
                    "plan_halva": _row[28].value,
                    "fact_halva": _row[29].value,
                    "plan_loyal": _row[32].value,
                    "fact_loyal": _row[33].value,
                }
            )

        return data_for_return


Функция которая сохраняет значения в БД:
@admin.register(models.KPIBaseNormative)
class KPIBaseNormativeAdmin(ImportXslxAdminMixin, admin.ModelAdmin):
    readonly_fields = (
        'profile',        'plan_KVC',        'fact_KVC',        'plan_FZ_PU',        'fact_FZ_PU',        'plan_halva',        'fact_halva',        'plan_loyal',        'fact_loyal',        'update_date',    )
    def load_file_xls_handler(self, request):
        file = request.FILES['file'].read()

        try:
            exporter = ImportFile(BytesIO(file))
            data = exporter.import_file_kpi_base_normative()
        except:
            self.message_user(request, 'Файл xslx не соответствует формату', messages.ERROR)
            return redirect('../load_file_xls_page')

        models.KPIBaseNormative.objects.all().delete()

        object = []

        for row in data:
            try:
                object.append(
                    models.KPIBaseNormative(
                        profile=Profile.objects.get(user__username=row["login"]),                        plan_KVC=int(row['plan_KVC']),                        fact_KVC=int(row['fact_KVC']),                        plan_FZ_PU=int(row['plan_FZ_PU']),                        fact_FZ_PU=int(row['fact_FZ_PU']),                        plan_halva=int(row['plan_halva']),                        fact_halva=int(row['fact_halva']),                        plan_loyal=int(row['plan_loyal']),                        fact_loyal=int(row['fact_loyal']),                    )
                )
            except Profile.DoesNotExist:
                continue        models.KPIBaseNormative.objects.bulk_create(object)

        return super(KPIBaseNormativeAdmin, self).load_file_xls_handler(request)
  • Вопрос задан
  • 104 просмотра
Пригласить эксперта
Ваш ответ на вопрос

Войдите, чтобы написать ответ

Похожие вопросы