Упорядоченный набор запросов, основанный на атрибутах его первой дочерней модели, возвращает дублированные объекты. Django, DRF - PullRequest
1 голос
/ 10 января 2020

У меня проблемы с моим набором запросов. Я использую Django Rest Framework для возврата:

  1. списка всех событий,
  2. , которые имеют статус = "Опубликован"
  3. , упорядоченных по: сначала самое последнее предстоящее событие.

Задача :

Некоторые события имеют несколько дат. Вот почему я разделил даты в другой модели.

Теперь я хочу упорядочить событие (Parent) на основе его первой даты (Child).

Вот что я пытаюсь сделать:

class EventViewSet(viewsets.ModelViewSet):
    """
    API Endpoint to retrieve Events
    """
    today = timezone.now().date()
    published_events = Event.objects.filter(status__exact="Published")
    ordered_events = published_events.order_by('date__start_date')
    queryset = ordered_events
    serializer_class = EventSerializer
    lookup_field = 'slug'

Вот мои модели:

Событие (родительское):

class Event(TimeStampedModel):
    DRAFT = "Draft"
    EXPIRED = "Expired"
    PRIVATE = "Private"
    PUBLISHED = "Published"
    EVENT_STATUS_CHOICES = [
        (DRAFT, 'Draft'),
        (EXPIRED, 'Expired'),
        (PRIVATE, 'Private'),
        (PUBLISHED, 'Published')
    ]

    name = models.CharField(max_length=250)
    location = models.ForeignKey(Location, on_delete=models.CASCADE)
    description = models.TextField(blank=True)
    status = models.CharField(max_length=50, choices=EVENT_STATUS_CHOICES, default=DRAFT)

    def event_dates(self):
        """
        Returns all dates of an event
        """
        try:
            date_list = []
            for date in self.dates.order_by('start_date'):
                date_list.append(date.start_date.date())
            return date_list

        except IndexError:
            return "No Dates Specified"

    def event_start_date(self):
        """
        Returns the start date of the event
        """
        try:
            return self.dates.order_by('start_date')[0].start_date.date()
        except IndexError:
            return "No Date Specified"

    def event_start_time(self):
        """
        Returns the start time of the event
        """
        try:
            return self.dates.order_by('start_date')[0].start_date.time()
        except IndexError:
            return "No Time Specified"

Дата Модель (Дочерний):

class EventDate(TimeStampedModel):
    event = models.ForeignKey(Event, on_delete=models.CASCADE, related_name="dates")
    start_date = models.DateTimeField()
    end_date = models.DateTimeField(null=True)
    history = HistoricalRecords()

    def __str__(self):
        return str(self.start_date)

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


Как я могу вернуть набор запросов, который упорядочен на основе первой дочерней даты start_date, без возврата объекта для каждого ребенка?

Если это звучит странно, пожалуйста, дайте мне знать, и я постараюсь изо всех сил чтобы уточнить это.

Спасибо!

Ответы [ 2 ]

2 голосов
/ 10 января 2020

Вы можете сначала аннотировать максимальную дату ребенка и запрос заказа этим значением:

from django.db.models import Max
ordered_events = published_events.annotate(max_chuld_date=Max("date__start_date")).order_by("max_chuld_date")
1 голос
/ 10 января 2020

Вы можете добавить поле с именем first_date в модель события и заполнить его в сигнале сохранения.

Это дублирование, но, по крайней мере, оно упрощает ваш запрос.

class Event(TimeStampedModel):
    ...
    first_start_date = models.DateTimeField()

В сигналах:

def event_post_save(*, signal, instance, created, raw, **kwargs):
    start_dates = [i.start_date for i in instance.dates.values('start_date')]
    start_dates.sort()
    try:
        instance.first_start_date = start_dates[0]
    except IndexError:
        pass

Код не проверен, но дает вам идею.

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