Django: переменная фильтра - PullRequest
0 голосов
/ 03 мая 2019

В моем models.py я фильтрую для двух случаев.Я проверяю, есть ли:

  1. a ticket_on_sale
  2. ticket_on_sale_soon

Если 2) задано, но 1) нет, то методдолжен вернуть True.Я фильтрую на переменном уровне (после того, как база данных уже нажата).Интересно, есть ли более солидный путь?То, что я сделал, не чувствуется правильным.У вас есть предложения?

models.py

class Event(TimeStampedModel):
    organizer = models.ForeignKey(
        Organizer,
        on_delete=models.PROTECT,
        related_name='events',
    )  # PROTECT = don't allow to delete the organizer if an event exists
    name = models.CharField(
        max_length=50,
        verbose_name=_("Event Title"),
    )
    slug = models.SlugField(
        validators=[SlugBlackList()],
        verbose_name=_("Event Link"),
    )
    currency = models.CharField(
        max_length=10,
        choices=CURRENCY_CHOICES,
        verbose_name=_("Currency"),
    )
    status = models.CharField(
        max_length=8,
        choices=EventStatus.CHOICES,
        default=EventStatus.DRAFT,
        verbose_name=_("Status"),
    )
    venue_address = models.TextField(
        null=True,
        blank=True,
        verbose_name=_("Location address"),
    )
    start_date = models.DateTimeField(verbose_name=_("Start date"))
    end_date = models.DateTimeField(verbose_name=_("End date"))

@cached_property
def only_scheduled_tickets(self):
    tickets = self.tickets.all()

    ticket_on_sale = list(filter(
        lambda ticket: ticket.is_on_sale() and ticket.is_available(),
        tickets,
    ))

    ticket_on_sale_soon = list(filter(
        lambda ticket: ticket.is_on_sale() and not ticket.is_available(),
        tickets,
    ))

    if ticket_on_sale_soon and not ticket_on_sale:
        return True


class Ticket(TimeStampedModel):
        event = models.ForeignKey(
            Event,
            on_delete=models.CASCADE,
            related_name='tickets',
        )  # CASCADE = delete the ticket if the event is deleted
        tax = models.ForeignKey(
            'Tax',
            on_delete=models.PROTECT,
            related_name='tickets',
            blank=True,
            null=True,
        )  # PROTECT = don't allow to delete the ticket tax if a ticket exists
        name = models.CharField(
            max_length=100,
            verbose_name=_("Ticket Name"),
        )
        price_gross = models.PositiveIntegerField(
            verbose_name=_("Price gross"),
        )
        description = models.TextField(
            null=True,
            blank=True,
        )
        start_at = models.DateTimeField(
            null=True,
            blank=True,
            verbose_name=_("Ticket sale starts at"),
        )
        end_at = models.DateTimeField(
            null=True,
            blank=True,
            verbose_name=_("Ticket sale ends at"),
        )
        quantity = models.PositiveIntegerField(
            verbose_name=_("Quantity"),
        )
        status = models.CharField(
            max_length=8,
            choices=TicketStatus.CHOICES,
            default=TicketStatus.ON_SALE,
            verbose_name=_("Status"),
        )

1 Ответ

0 голосов
/ 03 мая 2019

Чтобы получить поле on_sale_soon в вашем TicketQuerySet, вам может понадобиться аннотация, например

from datetime import date
from django.db import models
from django.db.models import Q, Value

tickets = Ticket.objects.annotate(
    on_sale_soon=Case(
        When(start_at__lte=date.today() + datetime.timedelta(days=10), then=Value(True, models.BooleanField())),
             default=Value(False, models.BooleanField()),
             output_field=models.BooleanField()
        )
    )
)

Впоследствии, если вы хотите получить билеты, которые скоро появятся в продаже, но еще не поступили, вы можете сделать

tickets = tickets.objects.exclude(status=TicketStatus.ON_SALE)
tickets = tickets.filter(on_sale_soon=True)

Преимущество этого состоит в том, что все будет выполнено на сервере БД в одном запросе.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...