@deus97

Как сделать пагинацию в Django для итерируемых в шаблоне объектов?

Есть задача вывести 50 000 сотрудников в иерархическом порядке на веб страницу Django.
Столько записей страница вывести не в состоянии, поэтому решил сделать пагинацию.
Но проблема в том, что у меня всего один объект - главный работник (Ashley Roberts), уже у которого есть подчиненные, и которые выводятся в шаблоне через итерацию этого самого единственного работника.
Возможно как-то сделать пагинацию для обьектов, которые выводятся через цикл?
Или возможно я зашел не с той стороны решения задачи, как тогда будет правильнее сделать?

Выглядит это так:
64a3c322801c7266269778.png

models.py
class Employee(models.Model):
    id = models.AutoField(primary_key=True)
    name = models.CharField(max_length=100)
    email = models.EmailField(null=True)
    hire_date = models.DateField(default=timezone.now)
    position = models.CharField(max_length=100)
    parent = models.ForeignKey('self', on_delete=models.CASCADE, null=True, blank=True, related_name='subordinates')

    def __str__(self):
        return self.name


view.py
def index(request):
    employees = Employee.objects.all()
    # print("qyery: ", employees)

    employees = [i for i in employees]

    # print("Employees:", employees)

    # return employees list that shoul remove from iteration
    def clear_employers():
        parent_id_list = [i.parent_id for i in employees]  # [None, 1087, 1087]
        id_list = [i.id for i in employees]  # [1087, 1088, 1089]
        parent_id_equil_id = [id for id in  parent_id_list if id in id_list] # [1087, 1087]

        clear_workers = [] # workers that should remove for unrepeating in iteration in template
        for i, worker in enumerate(employees):
            # print(i, " | ", worker, " | ", worker.parent_id)

            if worker.parent_id in parent_id_equil_id:
                clear_workers.append(worker)
                #print("worker to remove:", worker.name)
        #print("clear_workers ****", clear_workers)
        return clear_workers

    # function that compare two lists and return list of needed employees
    def compare(*args):
        employees_res = [e for e in employees if e not in clear_employers()]

        return employees_res

    employees = compare(employees, clear_employers())
    print(employees)
    print("Change Employees:", len([subordinates_employees for subordinates_employees in employees]))



    paginator = Paginator(employees, 200)

    page_number = request.GET.get('page')
    page_obj = paginator.get_page(page_number)

    return render(request, "page/index.html", {'page_obj': page_obj})


html. Здесь семь вложенных циклов потому что иерархия из семи звеньев
{% block content %}
<center>
    <p class="h1">Hierarchy of workers</p>
</center>

<ul class="list-group m-2">
{% for employee in page_obj %}
<a class="list-group-item list-group-item-danger dropdown-toggle" href="#" role="button" data-bs-toggle="dropdown" aria-expanded="false">{{ employee.name }} - {{ employee.position }}</a>
 <ul class="dropdown-menu">
<li><a class="dropdown-item" href="#">Manager: {{ employee.parent }}</a></li>
<li><a class="dropdown-item" href="#">{{ employee.email }}</a></li>
<li><a class="dropdown-item" href="#">Hiring date: {{ employee.hire_date }}</a></li>
</ul>


    {% if employee.subordinates.all %}
    <ul>
    {% for sub_1 in employee.subordinates.all %}
    <a class="list-group-item list-group-item-warning dropdown-toggle" href="#" role="button" data-bs-toggle="dropdown" aria-expanded="false">{{ sub_1.name }} - {{ sub_1.position }}</a>
     <ul class="dropdown-menu">
    <li><a class="dropdown-item" href="#">Manager: {{ sub_1.parent }}</a></li>
    <li><a class="dropdown-item" href="#">{{ sub_1.email }}</a></li>
    <li><a class="dropdown-item" href="#">Hiring date: {{ sub_1.hire_date }}</a></li>
    </ul>  


        {% if sub_1.subordinates.all %}
        <ul class="">
        {% for sub_2 in sub_1.subordinates.all %}
        <a class="list-group-item list-group-item-info dropdown-toggle" href="#" role="button" data-bs-toggle="dropdown" aria-expanded="false">{{ sub_2.name }} - {{ sub_2.position }}</a>
        <ul class="dropdown-menu">
        <li><a class="dropdown-item" href="#">Manager: {{ sub_2.parent }}</a></li>
        <li><a class="dropdown-item" href="#">{{ sub_2.email }}</a></li>
        <li><a class="dropdown-item" href="#">Hiring date: {{ sub_2.hire_date }}</a></li>
        </ul> 
            {% if sub_2.subordinates.all %}
            <ul class="">
            {% for sub_3 in sub_2.subordinates.all %}
                <a class="list-group-item list-group-item-success dropdown-toggle" href="#" role="button" data-bs-toggle="dropdown" aria-expanded="false">{{ sub_3.name }} - {{ sub_3.position }}</a>

                {% if sub_3.subordinates.all %}
                <ul class="">
                {% for sub_4 in sub_3.subordinates.all %}
                <a class="list-group-item list-group-item-primary dropdown-toggle" href="#" role="button" data-bs-toggle="dropdown" aria-expanded="false">{{ sub_4.name }} - {{ sub_4.position }}</a>
                <ul class="dropdown-menu">
                <li><a class="dropdown-item" href="#">Manager: {{ sub_4.parent }}</a></li>
                <li><a class="dropdown-item" href="#">{{ sub_4.email }}</a></li>
                <li><a class="dropdown-item" href="#">Hiring date: {{ sub_4.hire_date }}</a></li>
                </ul> 
                    {% if sub_4.subordinates.all %}
                    <ul class="">
                    {% for sub_5 in sub_4.subordinates.all %}
                    <a class="list-group-item list-group-item-dark dropdown-toggle" href="#" role="button" data-bs-toggle="dropdown" aria-expanded="false">{{ sub_5.name }} - {{ sub_5.position }}</a>
                    <ul class="dropdown-menu">
                    <li><a class="dropdown-item" href="#">Manager: {{ sub_5.parent }}</a></li>
                    <li><a class="dropdown-item" href="#">{{ sub_5.email }}</a></li>
                    <li><a class="dropdown-item" href="#">Hiring date: {{ sub_5.hire_date }}</a></li>
                    </ul>  
                        {% if sub_5.subordinates.all %}
                        <ul class="">
                        {% for sub_6 in sub_5.subordinates.all %}
                        <a class="list-group-item list-group-item-light dropdown-toggle" href="#" role="button" data-bs-toggle="dropdown" aria-expanded="false">{{ sub_6.name }} - {{ sub_6.position }}</a>
                        <ul class="dropdown-menu">
                        <li><a class="dropdown-item" href="#">Manager: {{ sub_6.parent }}</a></li>
                        <li><a class="dropdown-item" href="#">{{ sub_6.email }}</a></li>
                        <li><a class="dropdown-item" href="#">Hiring date: {{ sub_6.hire_date }}</a></li>
                        </ul>  
                        {% endfor %}
                        </ul>
                        {% endif %} 
                    {% endfor %}
                    </ul>
                    {% endif %} 
                {% endfor %}
                </ul>
                {% endif %} 

            {% endfor %}
            </ul>
            {% endif %} 
        {% endfor %}
        </ul>
        {% endif %} 

    </li>
    {% endfor %}
    {% endif %}
{% endfor %}
</ul>
</ul>
  • Вопрос задан
  • 80 просмотров
Пригласить эксперта
Ответы на вопрос 1
trapwalker
@trapwalker
Программист, энтузиаст
В таких случаях обычно не разворачивают дерево начиная с какого-то уровня, иначе найти что-то полезное при наличии пагинации становится очень трудно. К примеру, у какого-нибудь Donald Duck'а будет две сотни подчиненных, а пагинация у вас ограничена пятьюдесятью. Показывая третью страницу вы не сможете отобразить всех сотрудников вверх по иерархии до корня дерева, поэтому не ясно будет кому они подчинены.

Чтобы удобнее было отображать такого рода деревья и не делать при этом огромное количество лишних запросов на каждое поддерево, формируют для каждого узла синтетический идентификатор, который включает через разделитель идентификаторы всей цепочки его родителей.
Упорядочивание узлов по такому идентификатору автоматически гарантирует их правильное расположение в дереве, а также позволит извлечь из одного идентификатора цепочку всех предков.
Ответ написан
Комментировать
Ваш ответ на вопрос

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

Войти через центр авторизации
Похожие вопросы