turn CellBase into an abstract class
This removes the django-model-utils dependency and will allow for a very simple serialisation of objects.
This commit is contained in:
parent
6cedb0e9d2
commit
5d53ad725d
|
@ -0,0 +1,41 @@
|
|||
# combo - content management system
|
||||
# Copyright (C) 2014 Entr'ouvert
|
||||
#
|
||||
# This program is free software: you can redistribute it and/or modify it
|
||||
# under the terms of the GNU Affero General Public License as published
|
||||
# by the Free Software Foundation, either version 3 of the License, or
|
||||
# (at your option) any later version.
|
||||
#
|
||||
# This program is distributed in the hope that it will be useful,
|
||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
# GNU Affero General Public License for more details.
|
||||
#
|
||||
# You should have received a copy of the GNU Affero General Public License
|
||||
# along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
from django.contrib.contenttypes.models import ContentType
|
||||
|
||||
class Library(object):
|
||||
"""Singleton object that serves as a registry of the classes
|
||||
providing page cells."""
|
||||
|
||||
def __init__(self):
|
||||
self.classes = {}
|
||||
|
||||
def get_cell_classes(self):
|
||||
return self.classes.values()
|
||||
|
||||
def get_cell_class(self, content_type_id):
|
||||
return self.classes[int(content_type_id)]
|
||||
|
||||
def register_cell_class(self, klass):
|
||||
content_type = ContentType.objects.get_for_model(klass)
|
||||
self.classes[content_type.id] = klass
|
||||
return klass
|
||||
|
||||
|
||||
library = Library() # singleton object
|
||||
register_cell_class = library.register_cell_class
|
||||
get_cell_classes = library.get_cell_classes
|
||||
get_cell_class = library.get_cell_class
|
|
@ -18,6 +18,7 @@ import inspect
|
|||
|
||||
from django.conf import settings
|
||||
from django.contrib.contenttypes.models import ContentType
|
||||
from django.core.exceptions import ObjectDoesNotExist
|
||||
from django.db import models
|
||||
from django.db.models import Max
|
||||
from django.forms import models as model_forms
|
||||
|
@ -27,9 +28,10 @@ from django.utils.safestring import mark_safe
|
|||
from django.utils.translation import ugettext_lazy as _
|
||||
|
||||
from ckeditor.fields import RichTextField
|
||||
from model_utils.managers import InheritanceManager
|
||||
import cmsplugin_blurp.utils
|
||||
|
||||
from .library import register_cell_class, get_cell_classes, get_cell_class
|
||||
|
||||
|
||||
class Page(models.Model):
|
||||
title = models.CharField(_('Title'), max_length=50)
|
||||
|
@ -83,10 +85,11 @@ class CellBase(models.Model):
|
|||
placeholder = models.CharField(max_length=20)
|
||||
order = models.PositiveIntegerField()
|
||||
|
||||
objects = InheritanceManager()
|
||||
|
||||
default_form_class = None
|
||||
|
||||
class Meta:
|
||||
abstract = True
|
||||
|
||||
@classmethod
|
||||
def get_verbose_name(cls):
|
||||
return cls._meta.verbose_name
|
||||
|
@ -94,11 +97,33 @@ class CellBase(models.Model):
|
|||
@classmethod
|
||||
def get_cell_content_types(cls):
|
||||
content_types = []
|
||||
for symbol in globals().values():
|
||||
if inspect.isclass(symbol) and issubclass(symbol, cls) and symbol is not cls:
|
||||
content_types.extend(symbol.get_content_types())
|
||||
for klass in get_cell_classes():
|
||||
content_types.extend(klass.get_content_types())
|
||||
return content_types
|
||||
|
||||
@classmethod
|
||||
def get_cells(cls, **kwargs):
|
||||
"""Returns the list of cells of various classes matching **kwargs"""
|
||||
cells = []
|
||||
for klass in get_cell_classes():
|
||||
cells.extend(klass.objects.filter(**kwargs))
|
||||
cells.sort(lambda x, y: cmp(x.order, y.order))
|
||||
return cells
|
||||
|
||||
def get_reference(self):
|
||||
"Returns a string that can serve as a unique reference to a cell"""
|
||||
return '%s-%s' % (ContentType.objects.get_for_model(self).id, self.id)
|
||||
|
||||
@classmethod
|
||||
def get_cell(cls, reference, **kwargs):
|
||||
"""Returns the cell matching reference, and eventual **kwargs"""
|
||||
content_id, cell_id = reference.split('-')
|
||||
try:
|
||||
klass = get_cell_class(content_id)
|
||||
except KeyError:
|
||||
raise ObjectDoesNotExist()
|
||||
return klass.objects.get(id=cell_id, **kwargs)
|
||||
|
||||
@classmethod
|
||||
def get_content_types(cls):
|
||||
return [{
|
||||
|
@ -117,13 +142,15 @@ class CellBase(models.Model):
|
|||
if self.default_form_class:
|
||||
return self.default_form_class
|
||||
|
||||
fields = [x.name for x in self._meta.local_concrete_fields if x.name != 'cellbase_ptr']
|
||||
fields = [x.name for x in self._meta.local_concrete_fields
|
||||
if x.name not in ('id', 'page', 'placeholder', 'order')]
|
||||
if not fields:
|
||||
return None
|
||||
|
||||
return model_forms.modelform_factory(self.__class__, fields=fields)
|
||||
|
||||
|
||||
@register_cell_class
|
||||
class TextCell(CellBase):
|
||||
text = RichTextField(_('Text'), null=True)
|
||||
|
||||
|
@ -134,6 +161,7 @@ class TextCell(CellBase):
|
|||
return mark_safe(self.text or '')
|
||||
|
||||
|
||||
@register_cell_class
|
||||
class FortuneCell(CellBase):
|
||||
class Meta:
|
||||
verbose_name = _('Fortune')
|
||||
|
@ -143,6 +171,7 @@ class FortuneCell(CellBase):
|
|||
return subprocess.check_output(['fortune'])
|
||||
|
||||
|
||||
@register_cell_class
|
||||
class BlurpCell(CellBase):
|
||||
blurp_key = models.CharField(max_length=50)
|
||||
|
||||
|
|
|
@ -64,9 +64,10 @@ $(function() {
|
|||
update: function(event, ui) {
|
||||
var new_order = Object();
|
||||
$('.cell').each(function(i, x) {
|
||||
new_order['pos_' + $(x).data('cell-id')] = i;
|
||||
var cell_suffix = $(x).data('cell-reference');
|
||||
new_order['pos_' + cell_suffix] = i;
|
||||
new_placeholder = $(x).closest('.placeholder').data('placeholder-key');
|
||||
new_order['ph_' + $(x).data('cell-id')] = new_placeholder;
|
||||
new_order['ph_' + cell_suffix] = new_placeholder;
|
||||
});
|
||||
$.ajax({
|
||||
url: $('#placeholders').data('cell-order-url'),
|
||||
|
|
|
@ -6,7 +6,7 @@
|
|||
<p>There are no options for this cell</p>
|
||||
{% endif %}
|
||||
<div class="buttons">
|
||||
<a rel="popup" href="{% url 'combo-manager-page-delete-cell' page_pk=page.id cell_pk=cell.id %}">Delete</a> | <a class="close-button" href="#">Close</a>
|
||||
<a rel="popup" href="{% url 'combo-manager-page-delete-cell' page_pk=page.id cell_reference=cell.get_reference %}">Delete</a> | <a class="close-button" href="#">Close</a>
|
||||
{% if form %}
|
||||
<button class="save">Save</button>
|
||||
{% endif %}
|
||||
|
|
|
@ -43,7 +43,7 @@
|
|||
<h2>{{ placeholder.name }}</h2>
|
||||
<div class="cell-list">
|
||||
{% for cell in placeholder.cells %}
|
||||
<div class="cell" data-cell-id="{{ cell.id }}">
|
||||
<div class="cell" data-cell-reference="{{ cell.get_reference }}">
|
||||
<h3>{{ cell.get_label }}</h3>
|
||||
<div>{% cell_form cell %}</div>
|
||||
</div>
|
||||
|
|
|
@ -23,10 +23,10 @@ register = template.Library()
|
|||
@register.simple_tag(takes_context=True)
|
||||
def cell_form(context, cell):
|
||||
context['url'] = reverse('combo-manager-page-edit-cell', kwargs={
|
||||
'page_pk': cell.page.id, 'cell_pk': cell.id})
|
||||
'page_pk': cell.page.id, 'cell_reference': cell.get_reference()})
|
||||
form_class = cell.get_default_form_class()
|
||||
if form_class:
|
||||
context['form'] = form_class(instance=cell, prefix='c%s' % cell.id)
|
||||
context['form'] = form_class(instance=cell, prefix='c%s' % cell.get_reference())
|
||||
else:
|
||||
context['form'] = None
|
||||
cell_form_template = template.loader.get_template('combo/cell_form.html')
|
||||
|
|
|
@ -30,9 +30,9 @@ urlpatterns = patterns('combo.views',
|
|||
url(r'^pages/(?P<page_pk>\w+)/add-cell-to-(?P<ph_key>\w+)/(?P<cell_type>\w+)/(?P<variant>[\w-]+)/$',
|
||||
views.page_add_cell,
|
||||
name='combo-manager-page-add-cell'),
|
||||
url(r'^pages/(?P<page_pk>\w+)/cell/(?P<cell_pk>\w+)/$', views.page_edit_cell,
|
||||
url(r'^pages/(?P<page_pk>\w+)/cell/(?P<cell_reference>[\w-]+)/$', views.page_edit_cell,
|
||||
name='combo-manager-page-edit-cell'),
|
||||
url(r'^pages/(?P<page_pk>\w+)/cell/(?P<cell_pk>\w+)/delete$', views.page_delete_cell,
|
||||
url(r'^pages/(?P<page_pk>\w+)/cell/(?P<cell_reference>[\w-]+)/delete$', views.page_delete_cell,
|
||||
name='combo-manager-page-delete-cell'),
|
||||
url(r'^pages/(?P<page_pk>\w+)/order$', views.cell_order,
|
||||
name='combo-manager-cell-order'),
|
||||
|
|
|
@ -16,6 +16,7 @@
|
|||
|
||||
from django.conf import settings
|
||||
from django.contrib.contenttypes.models import ContentType
|
||||
from django.core.exceptions import ObjectDoesNotExist
|
||||
from django.core.urlresolvers import reverse
|
||||
from django.forms import models as model_forms
|
||||
from django.http import HttpResponse, Http404
|
||||
|
@ -77,8 +78,7 @@ class PageView(DetailView):
|
|||
def get_context_data(self, **kwargs):
|
||||
context = super(DetailView, self).get_context_data(**kwargs)
|
||||
context['cell_types'] = CellBase.get_cell_content_types()
|
||||
cells = CellBase.objects.filter(page_id=self.object.id
|
||||
).order_by('order').select_subclasses()
|
||||
cells = CellBase.get_cells(page_id=self.object.id)
|
||||
template = self.object.template_name
|
||||
placeholders = []
|
||||
combo_template = settings.COMBO_PUBLIC_TEMPLATES.get(template)
|
||||
|
@ -99,7 +99,7 @@ class PageAddCellView(RedirectView):
|
|||
cell_class = ContentType.objects.get(id=cell_type).model_class()
|
||||
cell = cell_class(page_id=page_pk, placeholder=ph_key)
|
||||
cell.set_variant(variant)
|
||||
orders = [x.order for x in CellBase.objects.filter(page_id=page_pk)]
|
||||
orders = [x.order for x in CellBase.get_cells(page_id=page_pk)]
|
||||
if orders:
|
||||
cell.order = max(orders)+1
|
||||
else:
|
||||
|
@ -113,19 +113,17 @@ page_add_cell = PageAddCellView.as_view()
|
|||
class PageEditCellView(UpdateView):
|
||||
def get_object(self, queryset=None):
|
||||
page_pk = self.kwargs.get('page_pk')
|
||||
cell_pk = self.kwargs.get('cell_pk')
|
||||
cell_reference = self.kwargs.get('cell_reference')
|
||||
try:
|
||||
return CellBase.objects.get_subclass(id=cell_pk, page_id=page_pk)
|
||||
except CellBase.DoesNotExist:
|
||||
return CellBase.get_cell(cell_reference, page_id=page_pk)
|
||||
except ObjectDoesNotExist:
|
||||
raise Http404()
|
||||
|
||||
def get_prefix(self):
|
||||
return 'c%s' % self.kwargs.get('cell_pk')
|
||||
return 'c%s' % self.kwargs.get('cell_reference')
|
||||
|
||||
def get_form_class(self):
|
||||
cell = self.object
|
||||
fields = [x.name for x in cell._meta.local_concrete_fields if x.name != 'cellbase_ptr']
|
||||
return model_forms.modelform_factory(cell.__class__, fields=fields)
|
||||
return self.object.get_default_form_class()
|
||||
|
||||
def get_success_url(self):
|
||||
return reverse('combo-manager-page-view', kwargs={'pk': self.kwargs.get('page_pk')})
|
||||
|
@ -138,10 +136,10 @@ class PageDeleteCellView(DeleteView):
|
|||
|
||||
def get_object(self, queryset=None):
|
||||
page_pk = self.kwargs.get('page_pk')
|
||||
cell_pk = self.kwargs.get('cell_pk')
|
||||
cell_reference = self.kwargs.get('cell_reference')
|
||||
try:
|
||||
return CellBase.objects.get_subclass(id=cell_pk, page_id=page_pk)
|
||||
except CellBase.DoesNotExist:
|
||||
return CellBase.get_cell(cell_reference, page_id=page_pk)
|
||||
except ObjectDoesNotExist:
|
||||
raise Http404()
|
||||
|
||||
def get_success_url(self):
|
||||
|
@ -151,11 +149,12 @@ page_delete_cell = PageDeleteCellView.as_view()
|
|||
|
||||
|
||||
def cell_order(request, page_pk):
|
||||
for cell in CellBase.objects.filter(page_id=page_pk):
|
||||
for cell in CellBase.get_cells(page_id=page_pk):
|
||||
old_order = cell.order
|
||||
old_placeholder = cell.placeholder
|
||||
new_order = int(request.GET.get('pos_' + str(cell.id)))
|
||||
new_placeholder = request.GET.get('ph_' + str(cell.id))
|
||||
key_suffix = cell.get_reference()
|
||||
new_order = int(request.GET.get('pos_' + key_suffix))
|
||||
new_placeholder = request.GET.get('ph_' + key_suffix)
|
||||
if new_order != old_order or new_placeholder != old_placeholder:
|
||||
cell.order = new_order
|
||||
cell.placeholder = new_placeholder
|
||||
|
|
|
@ -32,8 +32,7 @@ def page(request):
|
|||
page = pages[-1]
|
||||
ctx = {
|
||||
'page': page,
|
||||
'page_cells': CellBase.objects.filter(page_id=page.id
|
||||
).order_by('order').select_subclasses(),
|
||||
'page_cells': CellBase.get_cells(page_id=page.id),
|
||||
'request': request,
|
||||
}
|
||||
template_name = settings.COMBO_PUBLIC_TEMPLATES[page.template_name]['template']
|
||||
|
|
|
@ -1,5 +1,4 @@
|
|||
Django==1.6
|
||||
django-ckeditor
|
||||
-e git+http://repos.entrouvert.org/gadjo.git/#egg=gadjo
|
||||
django-model-utils
|
||||
django-cmsplugin-blurp
|
||||
|
|
Loading…
Reference in New Issue