Sorry for the long text
Models are given:
User
Hierarchy
class Hierarchy (Model):
xowner = OneToOneField(User)
subordinates = ManyToManyField(User)
There are users, they can invite each other. The invitees, in turn, can accept the invite or reject it.
Suppose that Mark invited Masha, Katya and Dima. Masha accepted Mark’s invitation, and even invited Kolya herself.
On one tab, you need to display the hierarchy.
Continuing the example, Mark should have:
1st level: Masha, Katya, Dima
2nd level: Kolya and other guys
1st level for Mark - those whom he invited.
2nd level - those who were invited by people invited by Mark.
And so on.
Tell me how to implement it | what to familiarize yourself with to get closer to the result
Advertisement
Answer
As far as I understand, you want a tree, not a graph. In such cases To minimize database queries you need to modernize your hierarchy model
- Install django-mptt
- change model
from django.db import models
from django.conf import settings
from mptt.models import MPTTModel, TreeForeignKey
class Hierarchy(MPTTModel):
user = models.ForeignKey(settings.AUTH_USER_MODEL, on_delete=models.CASCADE)
owner = TreeForeignKey('self', on_delete=models.CASCADE, null=True, blank=True, related_name='subordinates')
class MPTTMeta:
parent_attr = 'owner'
level_attr = 'mptt_level'
order_insertion_by=['user']
- Get your list
from django.shortcuts import get_object_or_404
from .models import Hierarchy
# Get owner
owner = get_object_or_404(Hierarchy, pk=owner_id)
# Get tree users from database
users = Hierarchy.objects.filter(tree_id=owner.tree_id, level__gt=owner.level).select_related('user').order_by('level')
# serialize tree
users_list = [] # list levels users with users
users_on_level = [] # list of users of the current tree level
tree_level = owner.level # current tree level
for user in users:
if user.level > tree_level:
tree_level += 1
users_list.append(users_on_level)
users_on_level = []
users_on_level.append(user)
# output users
for level, users in enumerate(users_list, 1):
print(f"{level} - {', '.join(str(user.username) for user in users) }"