Projet

Général

Profil

0001-general-simplify-acquisition-of-parent-content-11110.patch

Frédéric Péters, 28 mai 2016 14:35

Télécharger (14,2 ko)

Voir les différences:

Subject: [PATCH] general: simplify acquisition of parent content (#11110)

 README                                            |  8 +---
 combo/data/migrations/0018_parentcontentcell.py   | 31 ++++++++++++++
 combo/data/migrations/0019_create_parent_cells.py | 35 +++++++++++++++
 combo/data/models.py                              | 52 +++++++++++------------
 combo/manager/templates/combo/page_view.html      | 11 -----
 combo/manager/views.py                            | 26 ++++++------
 combo/public/views.py                             | 39 ++++-------------
 tests/test_public.py                              |  3 +-
 8 files changed, 118 insertions(+), 87 deletions(-)
 create mode 100644 combo/data/migrations/0018_parentcontentcell.py
 create mode 100644 combo/data/migrations/0019_create_parent_cells.py
README
57 57
('order' attribute).
58 58

  
59 59
A placeholder can be marked as 'acquired' (see "footer" in the example above),
60
this makes its cells automatically inherited from a parent page; the presence
61
of a cell of type 'Unlock Marker' will stop this acquisition mechanism, this
62
makes it possible to have a different content for those placeholders in
63
specific pages or sections have the site.
64

  
65
  Note: in the case of placeholder acquisition the site index page will be
66
  inserted as the top of the page hierarchy.
60
this way a cell of "same as parent" type will automatically be added.
67 61

  
68 62

  
69 63
Settings
combo/data/migrations/0018_parentcontentcell.py
1
# -*- coding: utf-8 -*-
2
from __future__ import unicode_literals
3

  
4
from django.db import migrations, models
5

  
6

  
7
class Migration(migrations.Migration):
8

  
9
    dependencies = [
10
        ('auth', '0006_require_contenttypes_0002'),
11
        ('data', '0017_menucell_root_page'),
12
    ]
13

  
14
    operations = [
15
        migrations.CreateModel(
16
            name='ParentContentCell',
17
            fields=[
18
                ('id', models.AutoField(verbose_name='ID', serialize=False, auto_created=True, primary_key=True)),
19
                ('placeholder', models.CharField(max_length=20)),
20
                ('order', models.PositiveIntegerField()),
21
                ('slug', models.SlugField(verbose_name='Slug', blank=True)),
22
                ('public', models.BooleanField(default=True, verbose_name='Public')),
23
                ('restricted_to_unlogged', models.BooleanField(default=False, verbose_name='Restrict to unlogged users')),
24
                ('groups', models.ManyToManyField(to='auth.Group', verbose_name='Groups', blank=True)),
25
                ('page', models.ForeignKey(to='data.Page')),
26
            ],
27
            options={
28
                'verbose_name': 'Parent Content',
29
            },
30
        ),
31
    ]
combo/data/migrations/0019_create_parent_cells.py
1
# -*- coding: utf-8 -*-
2
from __future__ import unicode_literals
3

  
4
from django.conf import settings
5
from django.db import migrations, models
6

  
7
def create_parent_content_cells(apps, schema_editor):
8
    Page = apps.get_model('data', 'Page')
9
    UnlockMarkerCell = apps.get_model('data', 'UnlockMarkerCell')
10
    ParentContentCell = apps.get_model('data', 'ParentContentCell')
11
    for page in Page.objects.all():
12
        combo_template = settings.COMBO_PUBLIC_TEMPLATES.get(page.template_name)
13
        for placeholder_key, placeholder_value in combo_template['placeholders'].items():
14
            if not placeholder_value.get('acquired'):
15
                continue
16
            is_unlocked = UnlockMarkerCell.objects.filter(page=page,
17
                    placeholder=placeholder_key).count()
18
            if is_unlocked:
19
                continue
20
            # not unlocked -> add a new ParentContentCell
21
            cell, created = ParentContentCell.objects.get_or_create(
22
                    page=page, placeholder=placeholder_key, order=0)
23
            if created:
24
                cell.save()
25

  
26

  
27
class Migration(migrations.Migration):
28

  
29
    dependencies = [
30
        ('data', '0018_parentcontentcell'),
31
    ]
32

  
33
    operations = [
34
        migrations.RunPython(create_parent_content_cells),
35
    ]
combo/data/models.py
176 176
        fill_list(object_list)
177 177
        return reordered
178 178

  
179
    def get_unlocked_placeholders(self, cells=None):
180
        combo_template = settings.COMBO_PUBLIC_TEMPLATES.get(self.template_name)
181
        if self.slug == 'index':
182
            # on the site index page, there are no unlocked placeholder.
183
            return combo_template['placeholders'].keys()
184

  
185
        if cells is None:
186
            cells = CellBase.get_cells(page_id=self.id)
187

  
188
        # on the other page sites, look for unlock markers
189
        unlocked_placeholders = []
190
        for cell in cells:
191
            if not isinstance(cell, UnlockMarkerCell):
192
                continue
193
            if cell.page_id == self.id:
194
                unlocked_placeholders.append(cell.placeholder)
195
        return unlocked_placeholders
196

  
197
    def get_locked_placeholders(self, cells=None):
198
        combo_template = settings.COMBO_PUBLIC_TEMPLATES.get(self.template_name)
199
        lockable_placeholders = [x for x in combo_template['placeholders'] if (
200
            combo_template['placeholders'].get(x).get('acquired'))]
201
        unlocked_placeholders = self.get_unlocked_placeholders(cells)
202
        locked_placeholders = set(lockable_placeholders) - set(unlocked_placeholders)
203
        return list(locked_placeholders)
204

  
205 179
    def visibility(self):
206 180
        if self.public:
207 181
            return _('Public')
......
481 455

  
482 456
@register_cell_class
483 457
class UnlockMarkerCell(CellBase):
458
    # XXX: this is kept to smooth transitions, it should be removed once all
459
    # sites # have been migrated to ParentContentCell
484 460
    """Marks an 'acquired' placeholder as unlocked."""
485 461
    visible = False
486 462

  
......
715 691
    def get_default_form_class(self):
716 692
        from .forms import ParametersCellForm
717 693
        return ParametersCellForm
694

  
695

  
696
@register_cell_class
697
class ParentContentCell(CellBase):
698
    class Meta:
699
        verbose_name = _('Same as parent')
700

  
701
    def get_cells(self):
702
        if self.page.parent:
703
            parent_page = self.page.parent
704
        elif self.page.slug != 'index':
705
            parent_page = Page.objects.get(slug='index', parent=None)
706
        else:
707
            return []
708
        cells = CellBase.get_cells(placeholder=self.placeholder, page=parent_page)
709
        for i, cell in enumerate(cells):
710
            if not isinstance(cell, ParentContentCell):
711
                continue
712
            cells[i:i+1] = cell.get_cells()
713
            break
714
        return cells
715

  
716
    def render(self, context):
717
        return ''
combo/manager/templates/combo/page_view.html
63 63

  
64 64
</div>
65 65

  
66
{% if extra_placeholders %}
67
<div id="extra-placeholders">
68
<h2>Extra blocks</h2>
69
<ul>
70
{% for placeholder in extra_placeholders %}
71
  <li><a href="{% url 'combo-manager-page-add-cell' page_pk=object.id cell_type=unlock.cell_type_str variant=unlock.variant ph_key=placeholder.key %}">{{ placeholder.name }}</a></li>
72
{% endfor %}
73
</ul>
74
</div>
75
{% endif %}
76

  
77 66
</div> <!-- #sidebar -->
78 67

  
79 68
<div id="page-content">
combo/manager/views.py
31 31
from django.views.generic import (TemplateView, RedirectView, DetailView,
32 32
        CreateView, UpdateView, ListView, DeleteView, FormView)
33 33

  
34
from combo.data.models import Page, CellBase, UnlockMarkerCell
34
from combo.data.models import Page, CellBase, ParentContentCell
35 35
from combo.data.library import get_cell_class
36 36
from combo import plugins
37 37

  
......
89 89
            initial['title'] = _('Home')
90 90
        return initial
91 91

  
92
    def form_valid(self, form):
93
        response = super(PageAddView, self).form_valid(form)
94
        if self.object.slug != 'index' or self.object.parent_id:
95
            combo_template = settings.COMBO_PUBLIC_TEMPLATES.get(self.object.template_name)
96
            for placeholder_key, placeholder in combo_template['placeholders'].items():
97
                if placeholder.get('acquired') is True:
98
                    ParentContentCell(page=self.object, placeholder=placeholder_key, order=0).save()
99

  
100
        return response
101

  
92 102
    def get_success_url(self):
93 103
        return reverse('combo-manager-page-view', kwargs={'pk': self.object.id})
94 104

  
......
161 171
        cells = CellBase.get_cells(page_id=self.object.id)
162 172
        template = self.object.template_name
163 173
        placeholders = []
164
        extra_placeholders = []
165 174
        combo_template = settings.COMBO_PUBLIC_TEMPLATES.get(template)
166 175

  
167
        unlocked_placeholders = self.object.get_unlocked_placeholders(cells)
168

  
169 176
        for placeholder_key, placeholder in combo_template['placeholders'].items():
170 177
            placeholder_dict = {
171 178
                'key': placeholder_key,
172 179
                'name': placeholder['name'],
173 180
            }
174
            if placeholder.get('acquired') and not placeholder_key in unlocked_placeholders:
175
                extra_placeholders.append(placeholder_dict)
176
            else:
177
                placeholder_dict['cells'] = [x for x in cells if (
178
                    x.placeholder == placeholder_key)]
179
                placeholders.append(placeholder_dict)
181
            placeholder_dict['cells'] = [x for x in cells if (
182
                x.placeholder == placeholder_key)]
183
            placeholders.append(placeholder_dict)
180 184

  
181
        context['unlock'] = UnlockMarkerCell.get_cell_types()[0]
182 185
        context['placeholders'] = placeholders
183
        context['extra_placeholders'] = extra_placeholders
184 186
        return context
185 187

  
186 188
page_view = requires_csrf_token(PageView.as_view())
combo/public/views.py
35 35
except ImportError:
36 36
    get_idps = lambda: []
37 37

  
38
from combo.data.models import CellBase, Page
38
from combo.data.models import CellBase, Page, ParentContentCell
39 39

  
40 40

  
41 41
def login(request, *args, **kwargs):
......
96 96
            return HttpResponse(cell.render(context), content_type='text/html')
97 97

  
98 98

  
99
def extend_with_locked_placeholders_cells(cells, page, pages):
100
    locked_placeholders = page.get_locked_placeholders(cells)
101

  
102
    if locked_placeholders:
103
        # there are some acquired placeholders, look in parent pages for
104
        # appropriate content.
105
        try:
106
            # add the site index page as ultimate parent
107
            if pages[0].slug != 'index':
108
                pages.insert(0, Page.objects.get(slug='index'))
109
        except Page.DoesNotExist:
110
            pass
111
        unlocker_cells = CellBase.get_cells(page_id__in=[x.id for x in pages])
112
        found_placeholders = {}
113
        for parent_page in reversed(pages[:-1]):
114
            for placeholder in parent_page.get_unlocked_placeholders(unlocker_cells):
115
                if not placeholder in locked_placeholders:
116
                    continue
117
                if not placeholder in found_placeholders:
118
                    found_placeholders[placeholder] = parent_page.id
119
            if len(found_placeholders) == len(locked_placeholders):
120
                break
121

  
122
        # add found cells to the page cells
123
        for placeholder_key, page_id in found_placeholders.items():
124
            cells.extend([x for x in unlocker_cells if x.page_id == page_id and
125
                x.placeholder == placeholder_key])
99
def extend_with_parent_cells(cells):
100
    for cell in cells:
101
        if not isinstance(cell, ParentContentCell):
102
            continue
103
        idx = cells.index(cell)
104
        cells[idx:idx+1] = cell.get_cells()
126 105

  
127 106

  
128 107
def skeleton(request):
......
187 166

  
188 167
    pages = selected_page.get_parents_and_self()
189 168
    cells = CellBase.get_cells(page_id=selected_page.id)
190
    extend_with_locked_placeholders_cells(cells, selected_page, pages)
169
    extend_with_parent_cells(cells)
191 170

  
192 171
    combo_template = settings.COMBO_PUBLIC_TEMPLATES[selected_page.template_name]
193 172

  
......
259 238
        return HttpResponseRedirect(page.redirect_url)
260 239

  
261 240
    cells = CellBase.get_cells(page_id=page.id)
262
    extend_with_locked_placeholders_cells(cells, page, pages)
241
    extend_with_parent_cells(cells)
263 242
    cells = [x for x in cells if x.is_visible(user=request.user)]
264 243

  
265 244
    ctx = {
tests/test_public.py
4 4
import urllib
5 5

  
6 6
from combo.wsgi import application
7
from combo.data.models import Page, CellBase, TextCell
7
from combo.data.models import Page, CellBase, TextCell, ParentContentCell
8 8

  
9 9
pytestmark = pytest.mark.django_db
10 10

  
......
60 60

  
61 61
    page = Page(title='Second', slug='second', template_name='standard')
62 62
    page.save()
63
    ParentContentCell(page=page, placeholder='footer', order=0).save()
63 64
    resp = app.get('/second', status=301)
64 65
    assert resp.location == 'http://localhost:80/second/'
65 66
    resp = app.get('/second/', status=200)
66
-