Projet

Général

Profil

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

Frédéric Péters, 02 juin 2016 14:21

Télécharger (15,5 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                            | 45 ++++++++++++++------
 combo/public/views.py                             | 39 ++++-------------
 tests/test_public.py                              |  3 +-
 8 files changed, 137 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
175 175
        fill_list(object_list)
176 176
        return reordered
177 177

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

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

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

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

  
204 178
    def visibility(self):
205 179
        if self.public:
206 180
            return _('Public')
......
485 459

  
486 460
@register_cell_class
487 461
class UnlockMarkerCell(CellBase):
462
    # XXX: this is kept to smooth transitions, it should be removed once all
463
    # sites # have been migrated to ParentContentCell
488 464
    """Marks an 'acquired' placeholder as unlocked."""
489 465
    visible = False
490 466

  
......
723 699
    def get_default_form_class(self):
724 700
        from .forms import ParametersCellForm
725 701
        return ParametersCellForm
702

  
703

  
704
@register_cell_class
705
class ParentContentCell(CellBase):
706
    class Meta:
707
        verbose_name = _('Same as parent')
708

  
709
    def get_cells(self):
710
        if self.page.parent:
711
            parent_page = self.page.parent
712
        elif self.page.slug != 'index':
713
            parent_page = Page.objects.get(slug='index', parent=None)
714
        else:
715
            return []
716
        cells = CellBase.get_cells(placeholder=self.placeholder, page=parent_page)
717
        for i, cell in enumerate(cells):
718
            if not isinstance(cell, ParentContentCell):
719
                continue
720
            cells[i:i+1] = cell.get_cells()
721
            break
722
        return cells
723

  
724
    def render(self, context):
725
        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

  
......
106 116
class PageSelectTemplateView(PageEditView):
107 117
    form_class = PageSelectTemplateForm
108 118

  
119
    def form_valid(self, form):
120
        old_template_name = self.get_object().template_name
121
        new_template_name = self.object.template_name
122
        response = super(PageSelectTemplateView, self).form_valid(form)
123
        if old_template_name != new_template_name:
124
            old_template = settings.COMBO_PUBLIC_TEMPLATES.get(old_template_name)
125
            new_template = settings.COMBO_PUBLIC_TEMPLATES.get(new_template_name)
126
            page_cells = CellBase.get_cells(page_id=self.object.id)
127
            for placeholder_key, placeholder in new_template['placeholders'].items():
128
                if not placeholder.get('acquired') is True:
129
                    continue
130
                if placeholder_key in old_template:
131
                    continue
132
                if [x for x in page_cells if x.placeholder == placeholder_key]:
133
                    # skip placeholders that already have cells
134
                    continue
135
                ParentContentCell(page=self.object, placeholder=placeholder_key, order=0).save()
136
        return response
137

  
109 138
page_select_template = PageSelectTemplateView.as_view()
110 139

  
111 140

  
......
161 190
        cells = CellBase.get_cells(page_id=self.object.id)
162 191
        template = self.object.template_name
163 192
        placeholders = []
164
        extra_placeholders = []
165 193
        combo_template = settings.COMBO_PUBLIC_TEMPLATES.get(template)
166 194

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

  
169 195
        for placeholder_key, placeholder in combo_template['placeholders'].items():
170 196
            placeholder_dict = {
171 197
                'key': placeholder_key,
172 198
                'name': placeholder['name'],
173 199
            }
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)
200
            placeholder_dict['cells'] = [x for x in cells if (
201
                x.placeholder == placeholder_key)]
202
            placeholders.append(placeholder_dict)
180 203

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

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

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

  
41 41

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

  
99 99

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

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

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

  
128 107

  
129 108
def skeleton(request):
......
188 167

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

  
193 172
    combo_template = settings.COMBO_PUBLIC_TEMPLATES[selected_page.template_name]
194 173

  
......
262 241
        return HttpResponseRedirect(page.redirect_url)
263 242

  
264 243
    cells = CellBase.get_cells(page_id=page.id)
265
    extend_with_locked_placeholders_cells(cells, page, pages)
244
    extend_with_parent_cells(cells)
266 245
    cells = [x for x in cells if x.is_visible(user=request.user)]
267 246
    cell_with_badges = CellBase.get_cells(cell_filter=lambda x: bool(x.get_badge))
268 247

  
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
-