Как я могу отфильтровать экземпляры подкласса? - PullRequest
0 голосов
/ 22 февраля 2020

Я пытаюсь отобразить все Event объекты, но только один указанный c экземпляр, если это также RecurringEvent.

models.py

from slugify import slugify

from django.db import models
from django.shortcuts import render

from home.models import TimestampedModel, NewsItem
from locations.models import Location
from .managers import EventManager, RecurringEventManager, RepeatInfoManager

class Event(NewsItem):
    name = models.CharField(max_length=255)
    slug = models.SlugField(default='', max_length=255, null=True, blank=True)
    description = models.TextField(null=True, blank=True)
    all_day = models.BooleanField(default=False)
    date_start = models.DateTimeField()
    date_end = models.DateTimeField(null=True, blank=True)
    location = models.ForeignKey(Location, null=True, blank=True, on_delete=models.CASCADE)
    objects = EventManager()

    def save(self, *args, **kwargs):
        self.slug = slugify(self.name)
        super().save(*args, **kwargs)

class RecurringEvent(Event):
    info = models.ForeignKey('RepeatInfo', on_delete=models.CASCADE, default=None)
    objects = RecurringEventManager()

class RepeatInfo(TimestampedModel):
    FREQUENCY_UNITS_CHOICES = [
        (0, 'No Repeat'),
        (1, 'Day(s)'),
        (2, 'Week(s)'),
        (3, 'Month(s)'),
        (4, 'Year(s)'),
    ]
    ENDS_CHOICES = [
        (0, 'Ends after maximum duration (1 year)'),
        (1, 'Ends on date'),
        (2, 'Ends after number of occurences'),
    ]

    weekly = models.BooleanField(default=True)
    frequency = models.PositiveSmallIntegerField(default=1)
    frequency_units = models.PositiveSmallIntegerField(default=0, choices=FREQUENCY_UNITS_CHOICES)
    ends = models.PositiveSmallIntegerField(default=0, choices=ENDS_CHOICES)
    ends_on = models.DateTimeField(null=True, blank=True, default=None)
    ends_after = models.PositiveSmallIntegerField(default=0)
    objects = RepeatInfoManager()

Я пробовал следующее:

events = []
_events = Event.objects.filter(date_start__gte=datetime.utcnow())
recurring_events_info = []
for event in _events:
    if isinstance(event, RecurringEvent):
        if event.info not in recurring_events_info:
            recurring_event = RecurringEvent.objects.filter(date_start__gte=datetime.utcnow(), info=event.info).order_by('-date_start').first()
            events.append(recurring_event)
            recurring_events_info.append(event.info)
    else:
        events.append(event)

, но проверка isinstance(event, RecurringEvent) всегда терпит неудачу. Как я могу получить только Event s, которые НЕ RecurringEvent s, поэтому я могу комбинировать их с RecurringEvent s, полученными таким образом?

events = []
recurring_events = RecurringEvent.objects.filter(date_start__gte=datetime.utcnow())
recurring_events_info = []
for event in recurring_events:
    if event.info not in recurring_events_info:
        recurring_event = RecurringEvent.objects.filter(date_start__gte=datetime.utcnow(), info=event.info).order_by('-date_start').first()
        events.append(recurring_event)
        recurring_events_info.append(event.info)

1 Ответ

0 голосов
/ 22 февраля 2020

Используйте .__class__.__base__ на ваших Event объектах для проверки их родительского типа.

for event in _events:
    # This checks if event object is a RecurringEvent (i.e. its parent is Event)
    if event.__class__.__base__ == Event:
        print('RecurringEvent object')
    # Otherwise its parent is not Event (i.e. it's not RecurrentEvent)
    else:
        print('Not RecurringEvent object')

Вместо этого вы можете поставить elif с проверкой, является ли базовый класс NewsItem, но я не знаю других частей вашего кода.

Надеюсь, это решит вашу проблему.

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