forked from rc/aircox
add manager for Related class; rename get_on_air as on_air + can retrieve by last logs instead of date
This commit is contained in:
parent
62380c054d
commit
960fcab65d
|
@ -648,7 +648,7 @@ class LogsPage(DatedListPage):
|
|||
|
||||
logs = []
|
||||
for date in context['nav_dates']['dates']:
|
||||
items = self.station.get_on_air(date)
|
||||
items = self.station.on_air(date = date)
|
||||
items = [ self.as_item(item) for item in items ]
|
||||
logs.append((date, items))
|
||||
return logs
|
||||
|
|
|
@ -32,6 +32,10 @@ from modelcluster.fields import ParentalKey
|
|||
from modelcluster.tags import ClusterTaggableManager
|
||||
from taggit.models import TaggedItemBase
|
||||
|
||||
# aircox
|
||||
import aircox.programs.models as programs
|
||||
|
||||
|
||||
|
||||
def related_pages_filter(reset_cache=False):
|
||||
"""
|
||||
|
@ -398,12 +402,12 @@ class DatedListBase(models.Model):
|
|||
return [ first + tz.timedelta(days=i)
|
||||
for i in range(0, self.nav_days) ]
|
||||
|
||||
def get_date_context(self, date):
|
||||
def get_date_context(self, date = None):
|
||||
"""
|
||||
Return a dict that can be added to the context to be used by
|
||||
a date_list.
|
||||
"""
|
||||
today = tz.now().today()
|
||||
today = tz.now().date()
|
||||
if not date:
|
||||
date = today
|
||||
|
||||
|
@ -809,3 +813,41 @@ class SectionList(ListBase, SectionItem):
|
|||
)
|
||||
return context
|
||||
|
||||
|
||||
@register_snippet
|
||||
class SectionTimetable(SectionItem,DatedListBase):
|
||||
panels = SectionItem.panels + DatedListBase.panels
|
||||
|
||||
def get_queryset(self, context):
|
||||
from aircox.cms.models import DiffusionPage
|
||||
diffs = []
|
||||
for date in context['nav_dates']['dates']:
|
||||
items = programs.Diffusion.objects.get_at(date).order_by('start')
|
||||
items = [ DiffusionPage.as_item(item) for item in items ]
|
||||
diffs.append((date, items))
|
||||
return diffs
|
||||
|
||||
def get_context(self, request, page, *args, **kwargs):
|
||||
context = super().get_context(request, page, *args, **kwargs)
|
||||
context.update(self.get_date_context())
|
||||
context['object_list'] = self.get_queryset(context)
|
||||
return context
|
||||
|
||||
|
||||
@register_snippet
|
||||
class SectionLogs(SectionItem):
|
||||
count = models.SmallIntegerField(
|
||||
_('count'),
|
||||
default = 5,
|
||||
help_text = _('number of items to display in the list'),
|
||||
)
|
||||
|
||||
panels = SectionItem.panels + [
|
||||
FieldPanel('count'),
|
||||
]
|
||||
|
||||
def get_context(self, request, page, *args, **kwargs):
|
||||
pass
|
||||
|
||||
|
||||
|
||||
|
|
|
@ -74,7 +74,7 @@ class DiffusionsMenu(GenericMenu):
|
|||
def get_queryset(self):
|
||||
return programs.Diffusion.objects.filter(
|
||||
type = programs.Diffusion.Type.normal,
|
||||
start__contains = tz.now().date() + tz.timedelta(days=2),
|
||||
start__contains = tz.now().date(),
|
||||
).order_by('start')
|
||||
|
||||
def get_title(self, item):
|
||||
|
|
|
@ -150,7 +150,7 @@ class Station(programs.Nameable):
|
|||
* archive: if false, exclude log of diffusion's archives from
|
||||
the queryset;
|
||||
"""
|
||||
qs = Log.get_for(model = models) \
|
||||
qs = Log.objects.get_for(model = models) \
|
||||
.filter(station = self, type = Log.Type.play)
|
||||
if not archives and self.dealer:
|
||||
qs = qs.exclude(
|
||||
|
@ -161,45 +161,66 @@ class Station(programs.Nameable):
|
|||
)
|
||||
return qs.order_by('date')
|
||||
|
||||
def get_on_air(self, date = None):
|
||||
|
||||
@staticmethod
|
||||
def __mix_logs_and_diff(diffs, logs, count = 0):
|
||||
"""
|
||||
Return a list of what should have normally been on air at the
|
||||
given date, ordered descending on the diffusion time
|
||||
Mix together logs and diffusion items ordering by their date.
|
||||
Diffs and Logs are assumed to be ordered by -date, and so is
|
||||
the resulting list
|
||||
"""
|
||||
# we fill a list with diff and retrieve logs that happened between
|
||||
# each to put them too there
|
||||
items = []
|
||||
diff_ = None
|
||||
for diff in diffs:
|
||||
logs_ = \
|
||||
logs.filter(date__gt = diff.end, date__lt = diff_.start) \
|
||||
if diff_ else logs.filter(date__gt = diff.end)
|
||||
diff_ = diff
|
||||
items.extends(logs_)
|
||||
items.append(diff)
|
||||
if count and len(items) >= count:
|
||||
break
|
||||
|
||||
if diff_ and not count or len(items) <= count:
|
||||
logs_ = logs.filter(date__lt = diff_.end)
|
||||
items.extend(logs_)
|
||||
|
||||
return items[:count] if count else items
|
||||
|
||||
|
||||
def on_air(self, date = None, count = 0):
|
||||
"""
|
||||
Return a list of what happened on air, based on logs and
|
||||
diffusions informations. The list is sorted by -date.
|
||||
|
||||
* date: only for what happened on this date;
|
||||
* count: number of items to retrieve if not zero;
|
||||
|
||||
Be careful with what you which for: the result is a plain list.
|
||||
|
||||
The list contains:
|
||||
- track logs: for the streamed programs;
|
||||
- diffusion: for the scheduled diffusions;
|
||||
* track logs: for the streamed programs;
|
||||
* diffusion: for the scheduled diffusions;
|
||||
"""
|
||||
# TODO: argument to get sound instead of tracks
|
||||
# FIXME: as an iterator?
|
||||
# TODO argument to get sound instead of tracks
|
||||
# TODO #Station
|
||||
date = date or tz.now().date()
|
||||
if date > datetime.date.today():
|
||||
return []
|
||||
|
||||
logs = Log.get_for(model = programs.Track) \
|
||||
.filter(date__contains = date) \
|
||||
.order_by('date')
|
||||
diffs = programs.Diffusion.objects.get_at(date) \
|
||||
.filter(type = programs.Diffusion.Type.normal) \
|
||||
.order_by('start')
|
||||
|
||||
# mix up
|
||||
items = []
|
||||
prev_diff = None
|
||||
for diff in diffs:
|
||||
logs_ = logs.filter(date__gt = prev_diff.end,
|
||||
date__lt = diff.start) \
|
||||
if prev_diff else \
|
||||
logs.filter(date__lt = diff.start)
|
||||
prev_diff = diff
|
||||
items.extend(logs_)
|
||||
items.append(diff)
|
||||
|
||||
# last logs
|
||||
if prev_diff:
|
||||
logs_ = logs.filter(date__gt = prev_diff.end)
|
||||
items.extend(logs_)
|
||||
return reversed(items)
|
||||
|
||||
logs = Log.objects.get_for(model = programs.Track) \
|
||||
.filter(station = self) \
|
||||
.order_by('-date')
|
||||
diffs = programs.Diffusion.objects \
|
||||
.filter(type = Diffusion.Type.normal) \
|
||||
.order_by('-date')
|
||||
if date:
|
||||
logs = logs.filter(date__contains = date)
|
||||
diffs = diffs.get_at(date)
|
||||
return self.__mix_logs_and_diff(diffs, logs, count)
|
||||
|
||||
|
||||
def save(self, make_sources = True, *args, **kwargs):
|
||||
|
|
|
@ -66,7 +66,7 @@ class Monitor:
|
|||
if not current_sound or not current_source:
|
||||
return
|
||||
|
||||
log = Log.get_for(model = programs.Sound) \
|
||||
log = Log.objects.get_for(model = programs.Sound) \
|
||||
.filter(station = self.station).order_by('date').last()
|
||||
|
||||
# only streamed
|
||||
|
@ -92,11 +92,11 @@ class Monitor:
|
|||
Log tracks for the given sound (for streamed programs); Called by
|
||||
self.trace
|
||||
"""
|
||||
logs = Log.get_for(model = programs.Track) \
|
||||
logs = Log.objects.get_for(model = programs.Track) \
|
||||
.filter(pk__gt = log.pk)
|
||||
logs = [ log.related_id for log in logs ]
|
||||
|
||||
tracks = programs.Track.get_for(object = log.related) \
|
||||
tracks = programs.Track.objects.get_for(object = log.related) \
|
||||
.filter(in_seconds = True)
|
||||
if tracks and len(tracks) == len(logs):
|
||||
return
|
||||
|
|
|
@ -127,7 +127,7 @@ class SoundInfo:
|
|||
if not os.path.exists(path):
|
||||
return
|
||||
|
||||
old = Track.get_for(object = sound)
|
||||
old = Track.objects.get_for(object = sound)
|
||||
if old:
|
||||
return
|
||||
|
||||
|
|
|
@ -45,6 +45,29 @@ def date_or_default(date, no_time = False):
|
|||
return date
|
||||
|
||||
|
||||
class RelatedManager(models.Manager):
|
||||
def get_for(self, object = None, model = None):
|
||||
"""
|
||||
Return a queryset that filter on the given object or model(s)
|
||||
|
||||
* object: if given, use its type and pk; match on models only.
|
||||
* model: one model or an iterable of models
|
||||
"""
|
||||
if not model and object:
|
||||
model = type(object)
|
||||
|
||||
if hasattr(model, '__iter__'):
|
||||
model = [ ContentType.objects.get_for_model(m).id
|
||||
for m in model ]
|
||||
qs = self.filter(related_type__pk__in = model)
|
||||
else:
|
||||
model = ContentType.objects.get_for_model(model)
|
||||
qs = self.filter(related_type__pk = model.id)
|
||||
if object:
|
||||
qs = qs.filter(related_id = object.pk)
|
||||
return qs
|
||||
|
||||
|
||||
class Related(models.Model):
|
||||
"""
|
||||
Add a field "related" of type GenericForeignKey, plus utilities.
|
||||
|
@ -60,28 +83,7 @@ class Related(models.Model):
|
|||
'related_type', 'related_id',
|
||||
)
|
||||
|
||||
@classmethod
|
||||
def get_for(cl, object = None, model = None):
|
||||
"""
|
||||
Return a queryset that filter on the given object or model(s)
|
||||
|
||||
* object: if given, use its type and pk; match on models only.
|
||||
* model: one model or list of models
|
||||
"""
|
||||
if not model and object:
|
||||
model = type(object)
|
||||
|
||||
if type(model) in (list, tuple):
|
||||
model = [ ContentType.objects.get_for_model(m).id
|
||||
for m in model ]
|
||||
qs = cl.objects.filter(related_type__pk__in = model)
|
||||
else:
|
||||
model = ContentType.objects.get_for_model(model)
|
||||
qs = cl.objects.filter(related_type__pk = model.id)
|
||||
|
||||
if object:
|
||||
qs = qs.filter(related_id = object.pk)
|
||||
return qs
|
||||
objects = RelatedManager()
|
||||
|
||||
class Meta:
|
||||
abstract = True
|
||||
|
|
Loading…
Reference in New Issue
Block a user