diff --git a/README.md b/README.md
index 508fab6..5a62d76 100644
--- a/README.md
+++ b/README.md
@@ -1,5 +1,6 @@
-# Aircox
-Platform to manage a radio. We use the power of Django
+
+
+Platform to manage a radio, schedules, website, and so on. We use the power of Django and Liquidsoap.
## Current features
* **streams**: multiple random music streams when no program is played. We also can specify a time range and frequency;
diff --git a/cms/models.py b/cms/models.py
index aef69e3..33e538b 100644
--- a/cms/models.py
+++ b/cms/models.py
@@ -92,15 +92,15 @@ class RelatedPostBase (models.base.ModelBase):
registry = {}
@classmethod
- def register (cl, key, model):
+ def register (cl, key, post_model):
"""
Register a model and return the key under which it is registered.
Raise a ValueError if another model is yet associated under this key.
"""
- if key in cl.registry and cl.registry[key] is not model:
+ if key in cl.registry and cl.registry[key] is not post_model:
raise ValueError('A model has yet been registered with "{}"'
.format(key))
- cl.registry[key] = model
+ cl.registry[key] = post_model
return key
@classmethod
@@ -137,13 +137,15 @@ class RelatedPostBase (models.base.ModelBase):
return rel
def __new__ (cl, name, bases, attrs):
+ # TODO: allow proxy models and better inheritance
if name == 'RelatedPost':
return super().__new__(cl, name, bases, attrs)
rel = cl.make_relation(name, attrs)
+ field_args = rel.field_args or {}
attrs['_relation'] = rel
attrs.update({ x:y for x,y in {
- 'related': models.ForeignKey(rel.model),
+ 'related': models.ForeignKey(rel.model, **field_args),
'__str__': lambda self: str(self.related)
}.items() if not attrs.get(x) })
@@ -207,6 +209,8 @@ class RelatedPost (Post, metaclass = RelatedPostBase):
* rel_to_post: auto update the post when related object is updated
* thread_model: generated by the metaclass, points to the RelatedPost
model generated for the bindings.thread object.
+ * field_args: dict of arguments to pass to the ForeignKey constructor,
+ such as: ForeignKey(related_model, **field_args)
Be careful with post_to_rel!
* There is no check of permissions when related object is synchronised
@@ -217,14 +221,15 @@ class RelatedPost (Post, metaclass = RelatedPostBase):
model = None
bindings = None # values to map { post_attr: rel_attr }
post_to_rel = False
- rel_to_post = True
+ rel_to_post = False
thread_model = None
+ field_args = None
def get_rel_attr(self, attr):
attr = self._relation.bindings.get(attr)
return getattr(self.related, attr) if attr else None
- def set_rel_attr(self, attr, value)
+ def set_rel_attr(self, attr, value):
if attr not in self._relation.bindings:
raise AttributeError('attribute {} is not bound'.format(attr))
attr = self._relation.bindings.get(attr)
@@ -240,13 +245,13 @@ class RelatedPost (Post, metaclass = RelatedPostBase):
if not rel.bindings:
return
- for attr, rel_attr in rel.bindings.items()
+ for attr, rel_attr in rel.bindings.items():
if attr == 'thread':
continue
value = getattr(self, attr) if hasattr(self, attr) else None
setattr(self.related, rel_attr, value)
- if self.thread_model:
+ if rel.thread_model:
thread = self.thread if not issubclass(thread, rel.thread_model) \
else None
self.set_rel_attr('thread', thread.related)
@@ -254,6 +259,19 @@ class RelatedPost (Post, metaclass = RelatedPostBase):
if save:
self.related.save()
+
+ @classmethod
+ def sync_from_rel(cl, rel, save = True):
+ """
+ Update a rel_to_post from a given rel object. Return -1 if there is no
+ related post to update
+ """
+ self = cl.objects.filter(related = rel)
+ if not self or not self.count():
+ return -1
+ self[0].rel_to_post(save)
+
+
def rel_to_post(self, save = True):
"""
Change the post using the related object bound values. Save the
@@ -264,7 +282,7 @@ class RelatedPost (Post, metaclass = RelatedPostBase):
if rel.bindings:
return
- for attr, rel_attr in rel.bindings.items()
+ for attr, rel_attr in rel.bindings.items():
if attr == 'thread':
continue
self.set_rel_attr
@@ -272,7 +290,7 @@ class RelatedPost (Post, metaclass = RelatedPostBase):
if hasattr(self.related, attr) else None
setattr(self, attr, value)
- if self.thread_model:
+ if rel.thread_model:
thread = self.get_rel_attr('thread')
thread = rel.thread_model.objects.filter(related = thread) \
if thread else None
@@ -282,11 +300,19 @@ class RelatedPost (Post, metaclass = RelatedPostBase):
if save:
self.save()
+ def __init__ (self, *kargs, **kwargs):
+ super().__init__(*kargs, **kwargs)
+ # we use this method for sync, in order to avoid intrusive code on other
+ # applications, e.g. using signals.
+ if self._relation.rel_to_post:
+ self.rel_to_post(save = False)
+
def save (self, *args, **kwargs):
+ # TODO handle when related change
if not self.title and self.related:
self.title = self.get_rel_attr('title')
if self._relation.post_to_rel:
- self.post_to_rel(False)
+ self.post_to_rel(save = True)
super().save(*args, **kwargs)
diff --git a/cms/templates/aircox/cms/base_site.html b/cms/templates/aircox/cms/base_site.html
index 6320787..7172f8a 100644
--- a/cms/templates/aircox/cms/base_site.html
+++ b/cms/templates/aircox/cms/base_site.html
@@ -8,7 +8,7 @@
-
+
{% if website.styles %}
{% endif %}
diff --git a/cms/templates/aircox/cms/detail.html b/cms/templates/aircox/cms/detail.html
index c022427..2859c4b 100644
--- a/cms/templates/aircox/cms/detail.html
+++ b/cms/templates/aircox/cms/detail.html
@@ -1,4 +1,4 @@
-{% extends embed|yesno:"aircox_cms/base_content.html,aircox_cms/base_site.html" %}
+{% extends embed|yesno:"aircox/cms/base_content.html,aircox/cms/base_site.html" %}
{% block title %}
{{ object.title }}
diff --git a/cms/templates/aircox/cms/list.html b/cms/templates/aircox/cms/list.html
index 1edd77d..abce834 100644
--- a/cms/templates/aircox/cms/list.html
+++ b/cms/templates/aircox/cms/list.html
@@ -1,4 +1,4 @@
-{% extends embed|yesno:"aircox_cms/base_content.html,aircox_cms/base_site.html" %}
+{% extends embed|yesno:"aircox/cms/base_content.html,aircox/cms/base_site.html" %}
{% load i18n %}
{% load thumbnail %}
diff --git a/cms/templates/aircox/cms/section.html b/cms/templates/aircox/cms/section.html
index 25febd0..494006c 100644
--- a/cms/templates/aircox/cms/section.html
+++ b/cms/templates/aircox/cms/section.html
@@ -1,4 +1,4 @@
-{% extends "aircox_cms/base_section.html" %}
+{% extends "aircox/cms/base_section.html" %}
{% block content %}
{% if title %}
diff --git a/cms/templates/aircox/cms/section_list.html b/cms/templates/aircox/cms/section_list.html
index 35589ee..f1eb561 100644
--- a/cms/templates/aircox/cms/section_list.html
+++ b/cms/templates/aircox/cms/section_list.html
@@ -1,4 +1,4 @@
-{% extends "aircox_cms/section.html" %}
+{% extends "aircox/cms/section.html" %}
{% load thumbnail %}
diff --git a/cms/views.py b/cms/views.py
index 0ca3e71..5ac4678 100644
--- a/cms/views.py
+++ b/cms/views.py
@@ -307,6 +307,8 @@ class Sections:
"""
@property
def content (self):
+ if not self.object.image:
+ return ''
return ''.format(
self.object.image.url
)
diff --git a/data/logo.png b/data/logo.png
new file mode 100644
index 0000000..cfab672
Binary files /dev/null and b/data/logo.png differ
diff --git a/data/logo.svg b/data/logo.svg
new file mode 100644
index 0000000..e3fbe21
--- /dev/null
+++ b/data/logo.svg
@@ -0,0 +1,165 @@
+
+
+
+