diff --git a/cms/models.py b/cms/models.py index 843fbad..41ecd40 100644 --- a/cms/models.py +++ b/cms/models.py @@ -147,7 +147,12 @@ class Post (models.Model, Routable): ) title = models.CharField ( _('title'), + max_length = 64, + ) + subtitle = models.CharField ( + _('subtitle'), max_length = 128, + blank = True, null = True, ) content = models.TextField ( _('description'), @@ -192,6 +197,8 @@ class Post (models.Model, Routable): """ Return an url to the post detail view. """ + if not self.pk: + return '' return self.reverse( routes.DetailRoute, pk = self.pk, slug = slugify(self.title) @@ -437,11 +444,6 @@ class RelatedPost (Post, metaclass = RelatedMeta): note: bound values can be any value, not only Django field. """ - defaults = None - """ - dict of `post_attr: value` that gives default value for the given - fields. - """ post_to_rel = False """ update related object when the post is saved, using bindings diff --git a/cms/routes.py b/cms/routes.py index c1f978e..74d79fd 100644 --- a/cms/routes.py +++ b/cms/routes.py @@ -93,7 +93,7 @@ class DetailRoute(Route): @classmethod def get_object(cl, model, request, pk, **kwargs): """ - * request is optional + * request: optional """ return model.objects.get(pk = int(pk)) @@ -107,7 +107,7 @@ class AllRoute(Route): @classmethod def get_queryset(cl, model, request, **kwargs): """ - * request is optional + * request: optional """ return model.objects.all() @@ -147,7 +147,7 @@ class ThreadRoute(Route): @classmethod def get_queryset(cl, model, request, thread_model, pk, **kwargs): """ - * request is optional + * request: optional """ thread = cl.get_thread(model, thread_model, pk) return model.get_siblings(thread_model = thread, thread_id = pk) @@ -176,15 +176,17 @@ class DateRoute(Route): ] @classmethod - def get_queryset(cl, model, request, year, month, day, **kwargs): + def get_queryset(cl, model, request, year, month, day, + attr='date', **kwargs): """ - * request is optional + * request: optional + * attr: name of the attribute to check the date against """ - return model.objects.filter( - date__year = int(year), - date__month = int(month), - date__day = int(day), - ) + return model.objects.filter(**{ + attr + '__year': int(year), + attr + '__month': int(month), + attr + '__day': int(day) + }) @classmethod def get_title(cl, model, request, year, month, day, **kwargs): @@ -208,7 +210,7 @@ class SearchRoute(Route): @classmethod def get_queryset(cl, model, request, q = None, **kwargs): """ - * request is required if q is None + * request: required if q is None """ q = request.GET.get('q') or q or '' qs = None diff --git a/cms/sections.py b/cms/sections.py index e5a2145..91ce968 100644 --- a/cms/sections.py +++ b/cms/sections.py @@ -285,6 +285,7 @@ class ListItem: behaves like it. """ title = None + subtitle = None content = None author = None date = None @@ -332,7 +333,8 @@ class List(Section): """ paginate_by = 4 - fields = [ 'date', 'time', 'image', 'title', 'content', 'info', 'actions' ] + fields = [ 'date', 'time', 'image', 'title', 'subtitle', 'content', 'info', + 'actions' ] """ Fields that must be rendered. """ diff --git a/notes.md b/notes.md index 61ca17f..97861c0 100644 --- a/notes.md +++ b/notes.md @@ -37,6 +37,8 @@ - mixcloud - seek bar + timer - remove from playing playlist -> stop + - date_by_list: + - sections' url - list of played diffusions and tracks when non-stop; # Long term TODO diff --git a/website/models.py b/website/models.py index 1f3ab82..359aeb9 100644 --- a/website/models.py +++ b/website/models.py @@ -50,13 +50,60 @@ class Program (cms.RelatedPost): auto_create = True -class Diffusion (cms.RelatedPost): +class DiffusionManager(models.Manager): + @staticmethod + def post_or_default(diff, post, create = True, save = False): + if not post and create: + post = Diffusion(related = diff.initial or diff) + if save: + post.save() + else: + post.rel_to_post() + if post: + post.date = diff.start + post.related = diff + return post + + def get_for(self, diffs, create = True, save = False): + """ + Get posts for the given related diffusion. Return a list + not a Queryset, ordered following the given list. + + Update the post objects to make date corresponding to the + diffusions. + + - diffs: a programs.Diffusion, or iterable of + programs.Diffusion. In the first case, return + an object instead of a list + - create: create a post for each Diffusion if missing + - save: save the created posts + """ + if not hasattr(diffs, '__iter__'): + qs = self.filter(related = diffs.initial or diff, + published = True) + return post_or_default(diffs, post, create, save) + + qs = self.filter(related__in = [ + diff.initial or diff for diff in diffs + ], published = True) + posts = [] + for diff in diffs: + post = qs.filter(related = diff.initial or diff).first() + post = self.post_or_default(diff, post, create, save) + if post: + posts.append(post) + return posts + + +class Diffusion(cms.RelatedPost): + objects = DiffusionManager() actions = [actions.Play, actions.AddToPlaylist] class Relation: model = programs.Diffusion bindings = { 'thread': 'program', + 'title': lambda post, rel: rel.program.name, 'date': 'start', } fields_args = { @@ -69,9 +116,16 @@ class Diffusion (cms.RelatedPost): def auto_create(object): return not object.initial - def __init__(self, *args, **kwargs): + def __init__(self, *args, rel_to_post = False, **kwargs): super().__init__(*args, **kwargs) + if rel_to_post and self.related: + self.rel_to_post() + self.fill_empty() + if not self.subtitle: + self.subtitle = _('Diffusion of the %(date)s') % { + 'date': self.related.start.strftime('%A %d/%m') + } @property def info(self): @@ -81,3 +135,14 @@ class Diffusion (cms.RelatedPost): 'day': self.related.initial.start.strftime('%A %d/%m') } + def url(self): + url = super().url() + if url or not self.related.initial: + return url + + post = Diffusions.objects.filter(related = self.related.initial) \ + .first() + return post.url() if post else '' + + + diff --git a/website/sections.py b/website/sections.py index fa3ee23..66fdd77 100644 --- a/website/sections.py +++ b/website/sections.py @@ -141,52 +141,9 @@ class Diffusions(sections.List): # .order_by('-start')[:self.prev_count]) #return r - def prepare_list(self, object_list): - """ - This function just prepare the list of object, in order to: - - have a good title - - given a stream to listen to if needed - """ - for post in object_list: - # title - if not hasattr(post, 'related') or \ - not hasattr(post.related , 'program'): - continue - name = post.related.program.name - if name not in post.title: - post.title = ': ' + post.title if post.title else \ - ' // ' + post.related.start.strftime('%A %d %B') - post.title = name + post.title - return object_list - def get_object_list(self): - diffs = self.get_diffs() - - posts = models.Diffusion.objects.filter(related__in = diffs) - r = [] - for diff in diffs: - diff_ = diff.initial if diff.initial else diff - post = next((x for x in posts if x.related == diff_), None) - if not post: - post = sections.ListItem(date = diff.start) - else: - post = sections.ListItem(post=post) - post.date = diff.start - - if diff.initial: - post.info = _('rerun of %(day)s') % { - 'day': diff.initial.start.strftime('%A %d/%m') - } - - if self.object: - post.update(self.object) - else: - thread = models.Program.objects. \ - filter(related = diff.program, published = True) - if thread: - post.update(thread[0]) - r.append(post) - return [ sections.ListItem(post=post) for post in r ] + diffs = self.get_diffs().order_by('start') + return models.Diffusion.objects.get_for(diffs) @property def url(self): @@ -255,7 +212,6 @@ class Sounds(sections.List): ] - class ListByDate(sections.List): """ List that add a navigation by date in its header. @@ -354,10 +310,11 @@ class Schedule(Diffusions,ListByDate): def get_object_list(self): date = self.date_or_default() - return routes.DateRoute.get_queryset( - models.Diffusion, self.request, date.year, date.month, - date.day - ).order_by('date') + diffs = routes.DateRoute.get_queryset( + programs.Diffusion, None, date.year, date.month, date.day, + attr = 'start' + ).order_by('start') + return models.Diffusion.objects.get_for(diffs, create = True) @staticmethod def get_date_url(date): @@ -400,6 +357,10 @@ class Logs(ListByDate): ) return post + @staticmethod + def make_diff(diff): + pass + def get_object_list(self): return [] station = self.view.website.station @@ -409,8 +370,11 @@ class Logs(ListByDate): date__year = int(year), date__month = int(month), date__day = int(day) ) - # TODO for each, exclude if there is a diffusion (that has not been logged) - return [ cl.make_item(log) for log in qs ] + # 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 ] @staticmethod def get_date_url(date):