Из-за цикла перед пагинацией Django paginator занимает слишком много времени. Как я могу решить эту проблему?

Меня попросили отобразить объект customer. Я пытался сделать пагинацию перед циклом, но не знаю как это сделать, потому что я думаю, что нужно передать все данные пагинатору при создании.

Это мое мнение

Я думаю, что проблема в том, что когда я вызываю функцию "get_customer_view_data", она запускает цикл внутри этой функции, и я полагаю, что это происходит каждый раз, когда я меняю страницу на пагинаторе, вызывая задержку

class CustomersView(AdminStaffRequiredMixin, TemplateView):
    template_name = 'customers/tables.html'

    def get(self, request, activeCustumers, *args, **kwargs):
        controller = CustomerViewController()

        date1 = request.GET.get('date1', 1)
        date2 = request.GET.get('date2', 1)
        customer_view_data = controller.get_customer_view_data(activeCustumers, date1, date2)

        page = request.GET.get('page', 1)

        paginator = Paginator(customer_view_data, 10)
        try:
            customers_data = paginator.page(page)
        except PageNotAnInteger:
            customers_data = paginator.page(1)
        except EmptyPage:
            customers_data = paginator.page(paginator.num_pages)

        context = {'object_list': customers_data, 'num': len(customer_view_data)}

        return render(request, self.template_name, context)

А это мой контроллер, в котором я отображаю данные:

class CustomerViewController(object):


    def get_customer_view_data(self, get_active_custumers,date1,date2):
        data = []
        dates = self.set_dates(date1, date2)
        if get_active_custumers == 1:
            obj = Organization.objects.filter(organizationmainapp__application__appinfoforstore__status=2,
                                              deleted=False,
                                              status=True, to_deleted=False)
        else:
            obj = Organization.objects.all()

        for o in obj:
            customer_view_data = Customer()

            customer_view_data.Organization_id = o.id
            customer_view_data.Organization_name = o.name

            try:
                customer_view_data.monthly_price_plan = o.organizationmainapp.application.applicationselectedplan.price_plan.monthly_price
            except Exception as e:
                print(e)
            try:
                if o.organizationmainapp.application.applicationselectedplan.price_plan.transaction_percent_price is not None:
                    customer_view_data.commission = o.organizationmainapp.application.applicationselectedplan.price_plan.transaction_percent_price
                else:
                    customer_view_data.commission = o.organizationmainapp.application.applicationselectedplan.price_plan.transaction_fixed_price
            except Exception as e:
                print(e)

            try:
                customer_view_data.App_name = o.organizationmainapp.application.appinfoforstore.store_name
            except Exception as e:
                print(e)

            try:
                customer_view_data.plan = o.organizationmainapp.application.applicationselectedplan.plan_name_stamp
            except Exception as e:
                print(e)

            try:
                customer_view_data.Total_last_Month_sales = self.get_total_sales(o.id,dates['start_date'],dates['end_date'])['total']
            except Exception as e:
                print(e)

            try:
                customer_view_data.Total_last_Month_sales_without_shipping_cost = \
                    self.get_total_sales(o.id, dates['start_date'], dates['end_date'])['total_without_shipping_cost']
            except Exception as e:
                print(e)
            try:
                customer_view_data.Main_mail = o.organizationmainapp.application.user.email
            except Exception as e:
                print(e)
            data.append(customer_view_data)

        return data

Пагинатору не нужны ВСЕ данные. Ему просто нужно знать, сколько будет строк данных. Ваш набор запросов (в вашем коде вы называете его obj, но более понятным и распространенным названием для него было бы qs или queryset)... может быть передан непосредственно Paginator(), и он вызовет count() на вашем наборе запросов, чтобы узнать, сколько строк будет выбрано.

Я говорю будет выбран, потому что пагинатор не извлекает все данные из базы данных, чтобы подсчитать их... он просто запрашивает базу данных для подсчета и получает число обратно... операция, которая намного быстрее, чем фактическое извлечение данных.

Затем пагинатор получает только строки, необходимые для отображения текущей страницы.

На вашем месте я бы полностью удалил CustomerViewController. Класс CustomerView сам по себе является вашим контроллером. Я бы поместил код, который создает и фильтрует набор запросов, непосредственно в представление, а затем код, который организует данные для каждой строки, в метод вашего класса Organization.

Затем просто передайте набор запросов в Paginator.

По мере отображения каждого экземпляра организации в шаблоне вызывайте (изнутри шаблона) метод, который возвращает нужные вам данные. Таким образом, вы не будете касаться строк, которые не будут отображаться на этой странице.

Не трогайте кверисет, просто передайте его в пагинатор, а затем используйте пагинатор. Например, не вызывайте len() на вашем наборе queryset, как вы это делаете. Поскольку queryset - это не список... он не содержит никаких данных пока вы не начнете итерировать его , или пока вы не сделаете определенные вещи, например, если вы построите список из него, или вызовете len() на нем... тогда вы вызовете запрос к базе данных и данные будут загружены. Вы же не хотите, чтобы это произошло, когда вы делаете пагинацию.

Простите

Вот как я решил эту проблему. Сначала я создаю пагинатор, а затем отображаю данные. Для целей пагинации я также передаю "organization_data" в контекст. Это не настоящий код, но он выглядит примерно так:

Мое мнение

class CustomersView(AdminStaffRequiredMixin, TemplateView):
template_name = 'customers/tables.html'

def get(self, request, *args, **kwargs):
    controller = CustomerViewController()
    organizations = controller.get_customer_view_data()
    
    page = request.GET.get('page', 1)

    paginator = Paginator(organizations, 15)
    try:
        organization_data = paginator.page(page)
    except PageNotAnInteger:
        organization_data = paginator.page(1)
    except EmptyPage:
        organization_data = paginator.page(paginator.num_pages)

    customers_data = controller.map_view_data(organization_data.object_list)
    # loop over each organization and return customers data
    context = {'object_list': customers_data, 'organization': organization_data}

    return render(request, self.template_name, context)
Вернуться на верх