remove Station model (to much trouble for few advantages); start new player; rename Post.detail_url to Post.url, same for ListItem; move Article into website app; add website.Sound post; work on lists;...

This commit is contained in:
bkfox
2016-06-12 21:34:31 +02:00
parent 13bf57b401
commit c3ae0e012c
18 changed files with 180 additions and 196 deletions

View File

@ -50,6 +50,9 @@ class MyModelPost(RelatedPost):
Note: it is possible to assign a function as a bounded value; in such case, the
function will be called using arguments **(post, related_object)**.
At rendering, the property *info* can be retrieved from the Post. It is however
not a field.
## Routes
Routes are used to generate the URLs of the website. We provide some of the
common routes: for the detail view of course, but also to select all posts or

View File

@ -91,7 +91,6 @@ def inject_inline(model, inline, prepend = False):
registry[model].inlines = inlines
admin.site.register(models.Article, PostAdmin)
admin.site.register(models.Comment, CommentAdmin)

View File

@ -166,7 +166,10 @@ class Post (models.Model, Routable):
)
return qs
def detail_url(self):
def url(self):
"""
Return an url to the post detail view.
"""
return self.route_url(
routes.DetailRoute,
pk = self.pk, slug = slugify(self.title)
@ -209,24 +212,6 @@ class Post (models.Model, Routable):
abstract = True
class Article (Post):
"""
Represent an article or a static page on the website.
"""
static_page = models.BooleanField(
_('static page'),
default = False,
)
focus = models.BooleanField(
_('article is focus'),
default = False,
)
class Meta:
verbose_name = _('Article')
verbose_name_plural = _('Articles')
class RelatedPostBase (models.base.ModelBase):
"""
Metaclass for RelatedPost children.
@ -356,6 +341,7 @@ class RelatedPost (Post, metaclass = RelatedPostBase):
class Meta:
abstract = True
# FIXME: declare a binding only for init
class Relation:
"""
Relation descriptor used to generate and manage the related object.

View File

@ -203,7 +203,7 @@ class ListItem:
date = None
image = None
info = None
detail_url = None
url = None
css_class = None
attrs = None
@ -222,8 +222,8 @@ class ListItem:
continue
if hasattr(post, i) and not getattr(self, i):
setattr(self, i, getattr(post, i))
if not self.detail_url and hasattr(post, 'detail_url'):
self.detail_url = post.detail_url()
if not self.url and hasattr(post, 'url'):
self.url = post.url()
class List(Section):
@ -243,6 +243,7 @@ class List(Section):
object_list = None
url = None
message_empty = _('nothing')
paginate_by = 4
fields = [ 'date', 'time', 'image', 'title', 'content', 'info' ]
image_size = '64x64'
@ -264,20 +265,32 @@ class List(Section):
def get_object_list(self):
return self.object_list
def get_context_data(self, *args, **kwargs):
context = super().get_context_data(*args, **kwargs)
def get_context_data(self, request, object=None, *args, **kwargs):
if request: self.request = request
if object: self.object = object
if kwargs: self.kwargs = kwargs
object_list = self.object_list or self.get_object_list()
if not object_list and not self.message_empty:
return
self.object_list = object_list
context = super().get_context_data(request, object, *args, **kwargs)
context.update({
'base_template': 'aircox/cms/section.html',
'list': self,
'object_list': object_list,
'object_list': object_list[:self.paginate_by]
if object_list and self.paginate_by else
object_list,
})
return context
def need_url(self):
"""
Return True if there should be a pagination url
"""
return self.paginate_by and self.paginate_by < len(self.object_list)
class Comments(List):
"""

View File

@ -1,51 +0,0 @@
{% extends "admin/base.html" %}
{% block extrahead %}
{% include 'autocomplete_light/static.html' %}
<style>
/** autocomplete override **/
.autocomplete-light-widget .deck [data-value] .remove {
float: right;
}
.autocomplete-light-widget .deck [data-value],
.autocomplete-light-widget .deck .choice {
display: block;
}
.control-group .add-related,
.inline-group .add-related {
vertical-align: bottom;
}
/** suit **/
.controls textarea,
.controls .vTextField {
width: calc(100% - 10px);
}
/** grappelli **/
.grp-autocomplete-wrapper-m2m:focus, .grp-autocomplete-wrapper-m2m.grp-state-focus,
.grp-autocomplete-wrapper-m2m {
background: rgba(255, 255, 255, 0.2);
border: none;
box-shadow: none;
}
.grp-autocomplete-wrapper-m2m ul.grp-repr li.grp-search {
background-color: #FDFDFD;
border: 1px solid #CCC;
}
.grp-autocomplete-wrapper-m2m ul.grp-repr li {
float: none;
display: block;
}
</style>
{% endblock %}

View File

@ -13,8 +13,8 @@
{% for k, v in item.attrs.items %}
{{ k }} = "{{ v|addslashes }}"
{% endfor %} >
{% if item.detail_url %}
<a href="{{ item.detail_url }}">
{% if item.url %}
<a href="{{ item.url }}">
{% endif %}
{% if 'image' in list.fields and item.image %}
<img src="{% thumbnail item.image list.image_size crop %}">
@ -65,7 +65,7 @@
</div>
{% if item.detail_url %}
{% if item.url %}
</a>
{% endif %}
{% empty %}

View File

@ -16,7 +16,7 @@ def threads(post, sep = '/'):
posts.insert(0, post)
return sep.join([
'<a href="{}">{}</a>'.format(post.detail_url(), post.title)
'<a href="{}">{}</a>'.format(post.url(), post.title)
for post in posts if post.published
])

View File

@ -118,10 +118,11 @@ class PostListView(PostBaseView, ListView):
if not self.list:
self.list = sections.List(
truncate = 32,
paginate_by = 0,
fields = ['date', 'time', 'image', 'title', 'content'],
)
else:
self.list = self.list()
self.list = self.list(paginate_by = 0)
self.template_name = self.list.template_name
self.css_class = self.list.css_class

View File

@ -51,8 +51,7 @@ class Website:
self.set_menu(menu)
if self.comments_routes:
self.register_comments_routes()
self.register_comments()
def name_of_model(self, model):
"""
@ -62,7 +61,7 @@ class Website:
if model is _model:
return name
def register_comments_routes(self):
def register_comments(self):
"""
Register routes for comments, for the moment, only
ThreadRoute