From 733acf20ef8bed5127837f6dbe0dff37fc6870a4 Mon Sep 17 00:00:00 2001 From: bkfox Date: Sat, 9 Jul 2016 00:05:11 +0200 Subject: [PATCH] remove get_content() function in sections; add is_empty() and message_empty() for all sections + hiding if needed; adapt; section Content is now child of Image; remove print() --- cms/sections.py | 112 +++++++++++++++++++++++++++++--------------- notes.md | 1 + website/actions.py | 1 - website/sections.py | 32 ++----------- 4 files changed, 78 insertions(+), 68 deletions(-) diff --git a/cms/sections.py b/cms/sections.py index d27bf47..008de08 100644 --- a/cms/sections.py +++ b/cms/sections.py @@ -97,6 +97,10 @@ class Section(Viewable, View): * title: title of the section * header: header of the section * footer: footer of the section + + * message_empty: if message_empty is not None, print its value as + content of the section instead of hiding it. This works also when + its value is an empty string (prints an empty string). """ template_name = 'aircox/cms/website.html' @@ -108,6 +112,8 @@ class Section(Viewable, View): header = '' footer = '' + message_empty = None + request = None object = None kwargs = None @@ -132,8 +138,13 @@ class Section(Viewable, View): self.attrs['name'] = self.name self.attrs['id'] = self.name - def get_content(self): - return '' + def is_empty(self): + """ + Return True if the section content will be empty. This allows to + hide the section. + This must be implemented by the subclasses. + """ + return False def get_context_data(self, request = None, object = None, **kwargs): if request: self.request = request @@ -149,17 +160,21 @@ class Section(Viewable, View): 'title': self.title, 'header': self.header, 'footer': self.footer, - 'content': self.get_content(), + 'content': '', 'object': self.object, 'embed': True, } - def render(self, request, object=None, context_only=False, **kwargs): + def render(self, request, object=None, **kwargs): context = self.get_context_data(request=request, object=object, **kwargs) - if context_only: - return context - if not context: + + is_empty = self.is_empty() + if not context or (is_empty and not self.message_empty): return '' + + if is_empty and self.message_empty: + context['content'] = self.message_empty + context['embed'] = True return render_to_string(self.template_name, context, request=request) @@ -170,45 +185,61 @@ class Image(Section): Attributes: * url: relative image url - * rel_attr: name of the attribute of self.object to use + * img_attr: name of the attribute of self.object to use """ url = None - rel_attr = 'image' + img_attr = 'image' - def get_content(self, **kwargs): - if self.url is None: - image = getattr(self.object, self.rel_attr) - return ''.format(image.url) if image else '' - return ''.format(static(self.url)) + def get_image(self): + if self.url: + return static(self.url) + if hasattr(self.object, self.img_attr): + image = getattr(self.object, self.img_attr) + return (image and image.url) or None + def is_empty(self): + return not self.get_image() -class Content(Section): + def get_context_data(self, *args, **kwargs): + context = super().get_context_data(*args, **kwargs) + url = self.get_image() + if url: + context['content'] += ''.format(url) + return context + +class Content(Image): """ Render content using the self.content or relative to self.object. + Since it is a child of Image, can also render an image. Attributes: * content: raw HTML code to render - * rel_attr: name of the attribute of self.object to use - * re_image_attr: if true and there is an image on the current object, - render the object's image + * content_attr: name of the attribute of self.object to use """ + # FIXME: markup language -- coordinate with object's one (post/comment)? content = None - rel_attr = 'content' - rel_image_attr = 'image' + content_attr = 'content' def get_content(self): - if self.content is None: - content = getattr(self.object, self.rel_attr) - content = escape(content) - content = re.sub(r'(^|\n\n)((\n?[^\n])+)', r'

\2

', content) - content = re.sub(r'\n', r'
', content) + if self.content: + return self.content + if hasattr(self.object, self.content_attr): + return getattr(self.object, self.content_attr) or None - if self.rel_image_attr and hasattr(self.object, self.rel_image_attr): - image = getattr(self.object, self.rel_image_attr) - if image: - content = ''.format(image.url) + content - return content - return str(self.content) + def is_empty(self): + return super().is_empty() and not self.get_content() + + def get_context_data(self, *args, **kwargs): + context = super().get_context_data(*args, **kwargs) + content = self.get_content() + if content: + if not self.content: + content = escape(content) + content = re.sub(r'(^|\n\n)((\n?[^\n])+)', r'

\2

', content) + content = re.sub(r'\n', r'
', content) + + context['content'] += content + return context class ListItem: @@ -245,7 +276,7 @@ class ListItem: if hasattr(post, i) and not getattr(self, i): setattr(self, i, getattr(post, i)) if not self.url and hasattr(post, 'url'): - self.url = post.url() + self.url = post.url() if callable(post.url) else post.url class List(Section): @@ -264,7 +295,6 @@ class List(Section): object_list = None url = None - message_empty = _('nothing') paginate_by = 4 fields = [ 'date', 'time', 'image', 'title', 'content', 'info', 'actions' ] @@ -284,6 +314,9 @@ class List(Section): ListItem(item) for item in items ] + def is_empty(self): + return not self.object_list + def get_object_list(self): return self.object_list @@ -304,7 +337,8 @@ class List(Section): instances of Post or ListItem. If object_list is not given, call `get_object_list` to retrieve it. - Prepare the object_list using `self.prepare_list`. + Prepare the object_list using `self.prepare_list`, and make actions + for its items. Set `request`, `object`, `object_list` and `kwargs` in self. """ @@ -379,7 +413,7 @@ class Comments(List): css_class='comments' truncate = 0 fields = [ 'date', 'time', 'author', 'content' ] - message_empty = _('no comment yet') + message_empty = _('no comment has been posted yet') comment_form = None success_message = ( _('Your message is awaiting for approval'), @@ -419,7 +453,6 @@ class Comments(List): context.update({ 'comment_form': comment_form, }) - self.comment_form = None return context @@ -486,10 +519,12 @@ class Search(Section): """ # TODO: (later) autocomplete using exposures -> might need templates - def get_content(self): + def get_context_data(self, *args, **kwargs): import aircox.cms.routes as routes + context = super().get_context_data(*args, **kwargs) url = self.model.reverse(routes.SearchRoute) - return """ + + context['content'] += """
@@ -501,6 +536,7 @@ class Search(Section): }, submit_style = (self.no_button and 'style="display: none;"') or '', ) + return context @expose diff --git a/notes.md b/notes.md index 6647fdf..939b1ba 100644 --- a/notes.md +++ b/notes.md @@ -45,6 +45,7 @@ - player support diffusions with multiple archive files - view as grid - actions -> noscript case, think of accessibility +- comments edit/remove by the poster diff --git a/website/actions.py b/website/actions.py index 111a822..af8fcda 100644 --- a/website/actions.py +++ b/website/actions.py @@ -46,7 +46,6 @@ class AddToPlaylist(Action): from aircox.programs.models import Sound from aircox.website.models import Diffusion - print(object) if not in_list: return False diff --git a/website/sections.py b/website/sections.py index e178ba9..4e72804 100644 --- a/website/sections.py +++ b/website/sections.py @@ -244,8 +244,8 @@ class Sounds(sections.List): return sounds = programs.Sound.objects.filter( - diffusion = self.object.related - # public = True + diffusion = self.object.related, + public = True, ).order_by('type') return [ sections.ListItem( @@ -265,6 +265,7 @@ class Schedule(Diffusions): date = None nav_date_format = '%a. %d' fields = [ 'time', 'image', 'title'] + message_empty = '' def __init__(self, *args, **kwargs): super().__init__(*args, **kwargs) @@ -342,30 +343,3 @@ class Schedule(Diffusions): return None - -#class DatesOfDiffusion(sections.List): -# title = _('Dates of diffusion') -# -# def get_object_list(self): -# diffs = list(programs.Diffusion.objects. \ -# filter(initial = self.object.related). \ -# exclude(type = programs.Diffusion.Type.unconfirmed) -# ) -# diffs.append(self.object.related) -# -# items = [] -# for diff in sorted(diffs, key = lambda d: d.date, reverse = True): -# info = '' -# if diff.initial: -# info = _('rerun') -# if diff.type == programs.Diffusion.Type.canceled: -# info += ' ' + _('canceled') -# items.append( -# sections.List.Item(None, diff.start.strftime('%c'), info, None, -# 'canceled') -# ) -# return items -# -## TODO sounds -# -