Django - Поиск отсутствующих приглашений на мероприятие

Мне нужно узнать мнение сообщества о django. Я все еще учусь, и абстракция уровней является моей главной проблемой (по сравнению с PHP/SQL скриптом)

Вот выдержка из моих моделей:

Очень простой контакт, но с "уровнем" (например, базовый, золотой, ...)

class customer(models.Model):
    created_date = models.DateTimeField(auto_now_add = True, editable = False)
    modified_date = models.DateTimeField(auto_now = True, editable = False)

    surname = models.CharField(max_length=200)
    lastname = models.CharField(max_length=200)
    fk_level = models.ForeignKey(level, on_delete=models.CASCADE)
[...]

Мероприятие с клиентами (любое количество), на которое нужно пригласить:

class event(models.Model):
    created_date = models.DateTimeField(auto_now_add = True, editable = False)
    modified_date = models.DateTimeField(auto_now = True, editable = False)

    eventdate =  models.DateField('Date de la soirée')
    fk_customer = models.ManyToManyField(customer, blank=True)
[...]

Приглашения на мероприятие, для клиента.

class invite(models.Model):
    created_date = models.DateTimeField(auto_now_add = True, editable = False)
    modified_date = models.DateTimeField(auto_now = True, editable = False)

    fk_customer = models.ForeignKey(customer, on_delete=models.CASCADE)
    fk_event = models.ForeignKey(event, on_delete=models.CASCADE)
[...]

Описание уровня, с указанием количества приглашений, которые будут отправлены в зависимости от уровня клиента.

class level(models.Model):
    created_date = models.DateTimeField(auto_now_add = True, editable = False)
    modified_date = models.DateTimeField(auto_now = True, editable = False)

    name = models.CharField(max_length=200)
    eventinvites = models.IntegerField(default=2)
[...]

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

Итак, мне нужно для каждого события проверить, достаточно ли у нас приглашений, основываясь на уровне клиента.

Если нет "приглашений" на мероприятие для "базового" клиента, мне нужно перечислить "eventinvites" (2) приглашения (я могу управлять созданием, когда узнаю их количество). Если есть только 1 приглашение, то мне нужно перечислить только 1. А если их больше 1, то мне не нужно ничего делать.

В коде stantard python я, вероятно, пройдусь по событиям, затем для каждого из них и для каждого из клиентов, которые были приглашены, пройдусь по приглашениям и проверю, сколько у меня есть приглашений, которые соответствуют клиенту и событию. Если их меньше, чем "eventinvites", я бы добавил пару событие/клиент в список "to do".

Что-то вроде

1   missing_invites = []
2   for event in Events:
3      for invited_customer in (Customers where event.fk_customer):
4           invite_count = 0
5           for invites in (Invites where invite.fk_customer==invited_customer and
6                           invite.fk_event == event.id):
7               invite_count += 1
8           if invite_count < event.fk_customer.fk_level.eventinvites:
9               missing_invites += (event, invited_customer)

В Django я могу создать представление с событиями, приглашениями и клиентами в контексте. Я могу пройтись по событиям (строка 2), затем отфильтровать клиентов (строка 3):

views.py:

class MissingInvitesView(PermissionRequiredMixin, ListView):
    model = invite
    template_name = 'missing.html'

    def get_context_data(self, **kwargs):
        context = super().get_context_data(**kwargs)
        context["Events"] = event.objects.all()
        context["Customers"] = customer.objects.all()

And missing.html:

{% for event in Events %}
    {% for customer in Customers|invited_to:event.id %}

Это тоже может работать, я еще не работал с наборами.

{% for event in Events %}
    {% for customer in event.customer_set.all %}

Но как мне перейти к следующему шагу. Фильтрация два раза подряд

        {% for customer_invite in Invites|matching_customer:customer.id %}
            {% for customer_invite_for_event in customer_invite|for_event:event.id %}

Или также использовать сеты? Это лучше? Я знаю, что первый вариант может быть

        {% for customer_invite in customer.invite_set.all %}

Но как насчет второго?

С помощью этого я могу получить список существующих приглашений. Но как их подсчитать? И как отобразить отсутствующие ?

Я все еще работаю с общими (class) представлениями, потому что это проще. Должен ли я начать изучать стандартные (def) представления? Будет ли это работать?

Большое спасибо за помощь. Jm

В конце концов я выяснил, как выполнить свою задачу.

Missing.html был обновлен до :

{% for event in Events %}
    {% for customer in event.fk_customer.all %}
        {% with eventInvites=Invites|matchingEvent:event.id %}
            {% for newInvite in eventInvites|MissingInvitesFor:customer.id %}
                        <br>New Invite required
            {%endfor%}
        {%endwith%}
    {% endfor%}
{%endfor%}

и мои пользовательские теги:

@register.filter(name="matchingEvent")
def matchingEvent(invites, event_id):
    return invites.filter(fk_event=event_id).all()


@register.filter(name="MissingInvitesFor")
def MissingInvitesFor(invites, current_customer_id):
    current_customer = customer.objects.filter(id = current_customer_id).first()
    customer_level = current_customer.fk_userlevel
    required_invites = int(customer_level.eventinvites)
    existing_invites = invites.filter(fk_customer=current_customer_id).count() 
    return range(required_invites - existing_invites)

Возможно, это не самый эффективный и не самый чистый вариант (потому что я создаю новые запросы в custom_tags), но он работает.

Любые комментарии приветствуются.

Вернуться на верх