add manager for programs.Diffusion + adapt; list_by_date's date urls; website's section Log algorithm
This commit is contained in:
parent
6b7255112d
commit
e0edd7fc7d
|
@ -1,3 +1,5 @@
|
|||
import datetime
|
||||
|
||||
from django.db import models
|
||||
from django.utils import timezone as tz
|
||||
from django.conf.urls import url
|
||||
|
@ -176,17 +178,13 @@ class DateRoute(Route):
|
|||
]
|
||||
|
||||
@classmethod
|
||||
def get_queryset(cl, model, request, year, month, day,
|
||||
attr='date', **kwargs):
|
||||
def get_queryset(cl, model, request, year, month, day, **kwargs):
|
||||
"""
|
||||
* request: optional
|
||||
* attr: name of the attribute to check the date against
|
||||
"""
|
||||
return model.objects.filter(**{
|
||||
attr + '__year': int(year),
|
||||
attr + '__month': int(month),
|
||||
attr + '__day': int(day)
|
||||
})
|
||||
date = datetime.date(int(year), int(month), int(day))
|
||||
return model.objects.filter(date__contains = date)
|
||||
|
||||
@classmethod
|
||||
def get_title(cl, model, request, year, month, day, **kwargs):
|
||||
|
|
|
@ -108,7 +108,7 @@ class Monitor:
|
|||
.order_by('date').last()
|
||||
|
||||
if not diff_log or \
|
||||
not diff_log.related.is_date_in_my_range(now):
|
||||
not diff_log.related.is_date_in_range(now):
|
||||
return None, []
|
||||
|
||||
# sound has switched? assume it has been (forced to) stopped
|
||||
|
@ -138,10 +138,8 @@ class Monitor:
|
|||
now = tz.make_aware(tz.datetime.now())
|
||||
|
||||
args = {'start__gt': diff.start } if diff else {}
|
||||
diff = programs.Diffusion.get(
|
||||
now, now = True,
|
||||
diff = programs.Diffusion.objects.get_at(now).filter(
|
||||
type = programs.Diffusion.Type.normal,
|
||||
|
||||
sound__type = programs.Sound.Type.archive,
|
||||
sound__removed = False,
|
||||
**args
|
||||
|
|
2
notes.md
2
notes.md
|
@ -27,7 +27,6 @@
|
|||
- admin cms
|
||||
-> sections/actions and django decorator?
|
||||
-> enhance calendar with possible actions?
|
||||
- sections id generator
|
||||
|
||||
- website:
|
||||
- diffusions:
|
||||
|
@ -39,7 +38,6 @@
|
|||
- remove from playing playlist -> stop
|
||||
- date_by_list:
|
||||
- sections' url
|
||||
- list of played diffusions and tracks when non-stop;
|
||||
|
||||
# Long term TODO
|
||||
- automatic cancel of passed diffusion based on logs?
|
||||
|
|
|
@ -1,3 +1,4 @@
|
|||
import datetime
|
||||
import os
|
||||
import shutil
|
||||
import logging
|
||||
|
@ -36,7 +37,7 @@ def date_or_default(date, no_time = False):
|
|||
Return date or default value (now) if not defined, and remove time info
|
||||
if date_only is True
|
||||
"""
|
||||
date = date or tz.datetime.today()
|
||||
date = date or tz.now()
|
||||
if not tz.is_aware(date):
|
||||
date = tz.make_aware(date)
|
||||
if no_time:
|
||||
|
@ -576,6 +577,49 @@ class Program(Nameable):
|
|||
return qs[0] if qs else None
|
||||
|
||||
|
||||
class DiffusionManager(models.Manager):
|
||||
def get_at(self, date = None):
|
||||
"""
|
||||
Return a queryset of diffusions that have the given date
|
||||
in their range.
|
||||
|
||||
If date is a datetime.date object, check only against the
|
||||
date.
|
||||
"""
|
||||
date = date or tz.now()
|
||||
if issubclass(type(date), datetime.date):
|
||||
return self.filter(
|
||||
models.Q(start__contains = date) | \
|
||||
models.Q(end__contains = date)
|
||||
)
|
||||
|
||||
return self.filter(
|
||||
models.Q(start__lte = date, end__gte = date) |
|
||||
# FIXME: should not be here?
|
||||
models.Q(start__gte = date),
|
||||
).order_by('start')
|
||||
|
||||
def get_after(self, date = None):
|
||||
"""
|
||||
Return a queryset of diffusions that happen after the given
|
||||
date.
|
||||
"""
|
||||
date = date_or_default(date)
|
||||
return self.filter(
|
||||
start__gte = date,
|
||||
).order_by('start')
|
||||
|
||||
def get_before(self, date):
|
||||
"""
|
||||
Return a queryset of diffusions that finish before the given
|
||||
date.
|
||||
"""
|
||||
date = date_or_default(date)
|
||||
return self.filter(
|
||||
end__lte = date,
|
||||
).order_by('start')
|
||||
|
||||
|
||||
class Diffusion(models.Model):
|
||||
"""
|
||||
A Diffusion is an occurrence of a Program that is scheduled on the
|
||||
|
@ -594,6 +638,8 @@ class Diffusion(models.Model):
|
|||
- cancel: the diffusion has been canceled
|
||||
- stop: the diffusion has been manually stopped
|
||||
"""
|
||||
objects = DiffusionManager()
|
||||
|
||||
class Type(IntEnum):
|
||||
normal = 0x00
|
||||
unconfirmed = 0x01
|
||||
|
@ -642,52 +688,13 @@ class Diffusion(models.Model):
|
|||
return sounds.filter(type = Sound.Type.archive, removed = False). \
|
||||
order_by('path')
|
||||
|
||||
@classmethod
|
||||
def get(cl, date = None,
|
||||
now = False, next = False, prev = False,
|
||||
queryset = None,
|
||||
**filter_args):
|
||||
"""
|
||||
Return a queryset of diffusions, depending on value of now/next/prev
|
||||
- now: that have date in their start-end range or start after
|
||||
- next: that start after date
|
||||
- prev: that end before date
|
||||
|
||||
If queryset is not given, use self.objects.all
|
||||
|
||||
Diffusions are ordered by +start for now and next; -start for prev
|
||||
"""
|
||||
#FIXME: conflicts? ( + calling functions)
|
||||
date = date_or_default(date)
|
||||
if queryset is None:
|
||||
queryset = cl.objects
|
||||
|
||||
if now:
|
||||
return queryset.filter(
|
||||
models.Q(start__lte = date,
|
||||
end__gte = date) |
|
||||
models.Q(start__gte = date),
|
||||
**filter_args
|
||||
).order_by('start')
|
||||
|
||||
if next:
|
||||
return queryset.filter(
|
||||
start__gte = date,
|
||||
**filter_args
|
||||
).order_by('start')
|
||||
|
||||
if prev:
|
||||
return queryset.filter(
|
||||
end__lte = date,
|
||||
**filter_args
|
||||
).order_by('-start')
|
||||
|
||||
def is_date_in_my_range(self, date = None):
|
||||
def is_date_in_range(self, date = None):
|
||||
"""
|
||||
Return true if the given date is in the diffusion's start-end
|
||||
range.
|
||||
"""
|
||||
return self.start < date_or_default(date) < self.end
|
||||
date = date or tz.now()
|
||||
return self.start < date < self.end
|
||||
|
||||
def get_conflicts(self):
|
||||
"""
|
||||
|
|
|
@ -1,9 +1,11 @@
|
|||
import json
|
||||
import datetime
|
||||
|
||||
from django.utils import timezone as tz
|
||||
from django.utils.translation import ugettext as _, ugettext_lazy
|
||||
|
||||
import aircox.programs.models as programs
|
||||
import aircox.controllers.models as controllers
|
||||
import aircox.cms.models as cms
|
||||
import aircox.cms.routes as routes
|
||||
import aircox.cms.sections as sections
|
||||
|
@ -30,12 +32,12 @@ class Player(sections.Section):
|
|||
|
||||
@expose
|
||||
def on_air(cl, request):
|
||||
qs = programs.Diffusion.get(
|
||||
now = True,
|
||||
now = tz.now()
|
||||
qs = programs.Diffusion.objects.get_at(now).filter(
|
||||
type = programs.Diffusion.Type.normal
|
||||
)
|
||||
|
||||
if not qs or not qs[0].is_date_in_my_range():
|
||||
if not qs or not qs[0].is_date_in_range():
|
||||
return {}
|
||||
|
||||
qs = qs[0]
|
||||
|
@ -214,7 +216,8 @@ class Sounds(sections.List):
|
|||
|
||||
class ListByDate(sections.List):
|
||||
"""
|
||||
List that add a navigation by date in its header.
|
||||
List that add a navigation by date in its header. It aims to be
|
||||
used with DateRoute.
|
||||
"""
|
||||
template_name = 'aircox/website/list_by_date.html'
|
||||
message_empty = ''
|
||||
|
@ -253,15 +256,19 @@ class ListByDate(sections.List):
|
|||
return [ first + tz.timedelta(days=i) for i in range(0, self.nav_days) ]
|
||||
|
||||
def date_or_default(self):
|
||||
"""
|
||||
Return self.date or create a date if needed, using kwargs'
|
||||
year, month, day attributes if exists (otherwise, use today)
|
||||
"""
|
||||
if self.date:
|
||||
return self.date
|
||||
return datetime.date(self.date)
|
||||
elif self.kwargs and 'year' in self.kwargs:
|
||||
return tz.datetime(year = int(self.kwargs['year']),
|
||||
month = int(self.kwargs['month']),
|
||||
day = int(self.kwargs['day']),
|
||||
hour = 0, minute = 0, second = 0,
|
||||
microsecond = 0)
|
||||
return tz.now()
|
||||
return datetime.date(
|
||||
year = int(self.kwargs['year']),
|
||||
month = int(self.kwargs['month']),
|
||||
day = int(self.kwargs['day'])
|
||||
)
|
||||
return datetime.date.today()
|
||||
|
||||
def get_context_data(self, *args, **kwargs):
|
||||
context = super().get_context_data(*args, **kwargs)
|
||||
|
@ -270,6 +277,7 @@ class ListByDate(sections.List):
|
|||
dates = [ (date, self.get_date_url(date))
|
||||
for date in self.nav_dates(date) ]
|
||||
|
||||
# FIXME
|
||||
next_week = dates[-1][0] + tz.timedelta(days=1)
|
||||
next_week = self.get_date_url(next_week)
|
||||
|
||||
|
@ -289,18 +297,22 @@ class ListByDate(sections.List):
|
|||
@staticmethod
|
||||
def get_date_url(date):
|
||||
"""
|
||||
return a url to the list for the given date
|
||||
return an url for the given date
|
||||
"""
|
||||
return self.view.website.reverse(
|
||||
model = self.model, route = routes.DateRoute,
|
||||
year = date.year, month = date.month, day = date.day,
|
||||
)
|
||||
|
||||
@property
|
||||
def url(self):
|
||||
return None
|
||||
|
||||
|
||||
class Schedule(Diffusions,ListByDate):
|
||||
"""
|
||||
Render a list of diffusions in the form of a schedule
|
||||
"""
|
||||
model = models.Diffusion
|
||||
fields = [ 'time', 'image', 'title', 'content', 'info', 'actions' ]
|
||||
truncate = 30
|
||||
|
||||
|
@ -310,10 +322,7 @@ class Schedule(Diffusions,ListByDate):
|
|||
|
||||
def get_object_list(self):
|
||||
date = self.date_or_default()
|
||||
diffs = routes.DateRoute.get_queryset(
|
||||
programs.Diffusion, None, date.year, date.month, date.day,
|
||||
attr = 'start'
|
||||
).order_by('start')
|
||||
diffs = programs.Diffusion.objects.get_at(date).order_by('start')
|
||||
return models.Diffusion.objects.get_for(diffs, create = True)
|
||||
|
||||
@staticmethod
|
||||
|
@ -329,54 +338,58 @@ class Schedule(Diffusions,ListByDate):
|
|||
|
||||
class Logs(ListByDate):
|
||||
"""
|
||||
Return a list of played stream sounds and diffusions.
|
||||
Print a list of played stream tracks and diffusions.
|
||||
Note that for the moment we don't print if the track has been
|
||||
partially hidden by a scheduled diffusion
|
||||
"""
|
||||
model = controllers.Log
|
||||
|
||||
@staticmethod
|
||||
def make_item(log):
|
||||
def make_item(item):
|
||||
"""
|
||||
Return a list of items to add to the playlist.
|
||||
Only support Log related to a Track and programs.Diffusion
|
||||
"""
|
||||
if issubclass(type(log.related), programs.Diffusion):
|
||||
diff = log.related
|
||||
post = models.Diffusion.objects.filter(related = diff).first() \
|
||||
or models.Program.objects.filter(related = diff.program).first() \
|
||||
or ListItem(title = diff.program.name)
|
||||
post.date = diff.start
|
||||
return post
|
||||
|
||||
if issubclass(type(log.related), programs.Track):
|
||||
track = log.related
|
||||
post = ListItem(
|
||||
title = '{artist} — {name}'.format(
|
||||
artist = track.artist,
|
||||
name = track.name,
|
||||
),
|
||||
date = log.date,
|
||||
content = track.info,
|
||||
info = '♫',
|
||||
if issubclass(type(item), programs.Diffusion):
|
||||
return models.Diffusion.objects.get_for(
|
||||
item, create = True, save = False
|
||||
)
|
||||
|
||||
track = log.related
|
||||
post = ListItem(
|
||||
title = '{artist} — {name}'.format(
|
||||
artist = track.artist,
|
||||
name = track.name,
|
||||
),
|
||||
date = log.date,
|
||||
content = track.info,
|
||||
info = '♫',
|
||||
)
|
||||
return post
|
||||
|
||||
@staticmethod
|
||||
def make_diff(diff):
|
||||
pass
|
||||
|
||||
def get_object_list(self):
|
||||
return []
|
||||
station = self.view.website.station
|
||||
qs = station.get_played(
|
||||
models = [ programs.Diffusion, programs.Track ],
|
||||
).filter(
|
||||
date__year = int(year), date__month = int(month),
|
||||
date__day = int(day)
|
||||
)
|
||||
# TODO for each, exclude if there is a corresponding diffusion
|
||||
# (that has not been logged)
|
||||
# if diff and diff != last_diff:
|
||||
# r.append(cl.make_item
|
||||
# return [ cl.make_item(log) for log in qs ]
|
||||
date = self.date_or_default()
|
||||
if date > datetime.date.today():
|
||||
return []
|
||||
|
||||
logs = controllers.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)
|
||||
|
||||
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)
|
||||
|
||||
return list(map(self.make_item, items))
|
||||
|
||||
@staticmethod
|
||||
def get_date_url(date):
|
||||
return 'TODO'
|
||||
|
||||
|
|
Loading…
Reference in New Issue
Block a user