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:
bkfox 2016-07-25 15:03:54 +02:00
parent 62380c054d
commit 960fcab65d
7 changed files with 127 additions and 62 deletions

View File

@ -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

View File

@ -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

View File

@ -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):

View File

@ -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):

View File

@ -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

View File

@ -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

View File

@ -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