Skip to content
This repository was archived by the owner on Feb 26, 2024. It is now read-only.

Commit 87a85a0

Browse files
author
Greg Turner
committed
Merge branch 'feature/22-fix-publishing-of-fluent-contents' into develop
# Conflicts: # docs/changelog.md
2 parents d6643de + 457c280 commit 87a85a0

File tree

18 files changed

+535
-274
lines changed

18 files changed

+535
-274
lines changed

docs/changelog.md

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,25 @@
11
# Changelog
22

3+
## In development
4+
5+
* Fix bug where the content items and placeholders associated with a
6+
fluent content model (other than a page) were not included in the
7+
published copy.
8+
9+
* Provide `icekit.publishing.models.PublishableFluentContents` and
10+
`icekit.publishing.admin.PublishableFluentContentsAdmin` as base
11+
classes for fluent content models and admins, to help keep things
12+
DRY.
13+
14+
### Breaking changes
15+
16+
* Import model mixins `FluentFieldsMixin`, `LayoutFieldMixin`, and
17+
`ReadabilityMixin` from `icekit.mixins` module instead of
18+
`icekit.abstract_models`.
19+
20+
* Import admin mixin `FluentLayoutsMixin` from `icekit.admin_mixins`
21+
module instead of `icekit.admin`.
22+
323
## 0.14.1 (26 September 2016)
424

525
* ICEkit gets a facelift. Content editing now looks cleaner and easier to
@@ -21,6 +41,7 @@
2141

2242
* Tag Docker images during build on Travis CI for release versions.
2343

44+
2445
## 0.14 (20 September 2016)
2546

2647
* Update the recommended method of running projects via `Docker` and `go.sh`

docs/howto/page-types.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -83,7 +83,7 @@ Here's a rough guide:
8383
| Static | Yes | No | `FluentContentsPage` | `FluentContentsPageAdmin` |
8484
| Static | Yes | Yes | `PublishableFluentContentsPage` (use `PlaceholderField`s) | `(FluentContentsPageAdmin, PublishingAdmin)` |
8585
| Dynamic | No | No | `FluentFieldsMixin` | `FluentLayoutsMixin` |
86-
| Dynamic | No | Yes | `(FluentFieldsMixin, PublishingModel)` | `(FluentLayoutsMixin, PublishingAdmin)` |
86+
| Dynamic | No | Yes | `PublishableFluentContents` | `PublishableFluentContentsAdmin` |
8787
| Dynamic | Yes | No | `AbstractUnpublishableLayoutPage` | `UnpublishableLayoutPageAdmin` |
8888
| Dynamic | Yes | Yes | `AbstractLayoutPage` | `LayoutPageAdmin` |
8989

docs/howto/plugins.md

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -74,14 +74,14 @@ with two mixin classes:
7474

7575
# models.py
7676

77-
from icekit.abstract_models import FluentFieldsMixin
77+
from icekit.mixins import FluentFieldsMixin
7878

7979
class MyModel(FluentFieldsMixin, MyModelBase):
8080
...
8181

8282
# admin.py
8383

84-
from icekit.admin import FluentLayoutsMixin
84+
from icekit.admin_mixins import FluentLayoutsMixin
8585

8686
class MyModelAdmin(FluentLayoutsMixin, MyModelAdminBase):
8787
...

docs/topics/publishing.md

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -41,6 +41,11 @@ To make a `FluentContentsPage` model publishable:
4141
* subclass your model from `icekit.publishing.models.PublishableFluentContentsPage`
4242
* subclass your model's admin from `FluentContentsPageAdmin` and `icekit.publishing.admin.PublishingAdmin`
4343

44+
To make a fluent contents model (see [ContentsPlugins]) publishable:
45+
46+
* subclass your model from `icekit.publishing.models.PublishableFluentContents`
47+
* subclass your model's admin from `icekit.publishing.admin.PublishableFluentContentsAdmin`
48+
4449
#### Note: Validating slug uniqueness
4550

4651
In publishable models, both the draft and published slugs will be identical,
@@ -248,3 +253,5 @@ rendering related content for the public and for site admins:
248253
There has been an issue discovered where `ManyToMany` fields referring both
249254
ways on models have the many to many data cloned for published and
250255
unpublished objects. This is currently being worked on.
256+
257+
[ContentsPlugins]: ../howto/plugins.md

icekit/abstract_models.py

Lines changed: 0 additions & 108 deletions
Original file line numberDiff line numberDiff line change
@@ -5,122 +5,14 @@
55
# Compose concrete models from abstract models and mixins, to facilitate reuse.
66
from django.contrib.contenttypes.models import ContentType
77
from django.db import models
8-
from django.template.defaultfilters import striptags
98
from django.template.loader import get_template
109
from django.utils import encoding, timezone
1110
from django.utils.translation import ugettext_lazy as _
1211
from fluent_contents.analyzer import get_template_placeholder_data
13-
from fluent_contents.models import \
14-
ContentItemRelation, Placeholder, PlaceholderRelation
15-
from fluent_contents.rendering import render_content_items
16-
from icekit.tasks import store_readability_score
17-
from icekit.utils.readability.readability import Readability
18-
from unidecode import unidecode
1912

2013
from . import fields, plugins
2114

2215

23-
# MIXINS ######################################################################
24-
25-
26-
class LayoutFieldMixin(models.Model):
27-
"""
28-
Add ``layout`` field to models that already have ``contentitem_set`` and
29-
``placeholder_set`` fields.
30-
"""
31-
layout = models.ForeignKey(
32-
'icekit.Layout',
33-
blank=True,
34-
null=True,
35-
related_name='%(app_label)s_%(class)s_related',
36-
)
37-
38-
fallback_template = 'icekit/layouts/fallback_default.html'
39-
40-
class Meta:
41-
abstract = True
42-
43-
def get_layout_template_name(self):
44-
"""
45-
Return ``layout.template_name`` or `fallback_template``.
46-
"""
47-
if self.layout:
48-
return self.layout.template_name
49-
return self.fallback_template
50-
51-
52-
class FluentFieldsMixin(LayoutFieldMixin):
53-
"""
54-
Add ``layout``, ``contentitem_set`` and ``placeholder_set`` fields so we
55-
can add modular content with ``django-fluent-contents``.
56-
"""
57-
contentitem_set = ContentItemRelation()
58-
placeholder_set = PlaceholderRelation()
59-
60-
class Meta:
61-
abstract = True
62-
63-
# HACK: This is needed to work-around a `django-fluent-contents` issue
64-
# where it cannot handle placeholders being added to a template after an
65-
# object already has placeholder data in the database.
66-
# See: https://github.com/edoburu/django-fluent-contents/pull/63
67-
def add_missing_placeholders(self):
68-
"""
69-
Add missing placeholders from templates. Return `True` if any missing
70-
placeholders were created.
71-
"""
72-
content_type = ContentType.objects.get_for_model(self)
73-
result = False
74-
if self.layout:
75-
for data in self.layout.get_placeholder_data():
76-
placeholder, created = Placeholder.objects.update_or_create(
77-
parent_type=content_type,
78-
parent_id=self.pk,
79-
slot=data.slot,
80-
defaults=dict(
81-
role=data.role,
82-
title=data.title,
83-
))
84-
result = result or created
85-
return result
86-
87-
def placeholders(self):
88-
# return a dict of placeholders, organised by slot, for access in templates
89-
# use `page.placeholders.<slot_name>.get_content_items` to test if
90-
# a placeholder has any items.
91-
return dict([(p.slot, p) for p in self.placeholder_set.all().select_related()])
92-
93-
94-
# TODO: should be a sub-app.
95-
class ReadabilityMixin(models.Model):
96-
readability_score = models.DecimalField(max_digits=4, decimal_places=2, null=True)
97-
98-
class Meta:
99-
abstract = True
100-
101-
def extract_text(self):
102-
# return the rendered content, with HTML tags stripped.
103-
html = render_content_items(request=None, items=self.contentitem_set.all())
104-
return striptags(html)
105-
106-
def calculate_readability_score(self):
107-
try:
108-
return Readability(unidecode(self.extract_text())).SMOGIndex()
109-
except:
110-
return None
111-
112-
def store_readability_score(self):
113-
store_readability_score.delay(self._meta.app_label, self._meta.model_name, self.pk)
114-
115-
def save(self, *args, **kwargs):
116-
r = super(ReadabilityMixin, self).save(*args, **kwargs)
117-
self.store_readability_score()
118-
return r
119-
120-
121-
# MODELS ######################################################################
122-
123-
12416
class AbstractBaseModel(models.Model):
12517
"""
12618
Abstract base model.

icekit/admin.py

Lines changed: 0 additions & 34 deletions
Original file line numberDiff line numberDiff line change
@@ -10,9 +10,6 @@
1010
from django.contrib.contenttypes.models import ContentType
1111
from django.http import JsonResponse
1212
from django.utils.translation import ugettext_lazy as _
13-
from fluent_contents.admin import PlaceholderEditorAdmin
14-
from fluent_contents.analyzer import get_template_placeholder_data
15-
from fluent_contents.models import PlaceholderData
1613
from polymorphic.admin import PolymorphicParentModelAdmin
1714

1815
from icekit import models
@@ -44,37 +41,6 @@ def queryset(self, request, queryset):
4441
# MIXINS ######################################################################
4542

4643

47-
class FluentLayoutsMixin(PlaceholderEditorAdmin):
48-
"""
49-
Mixin class for models that have a ``layout`` field and fluent content.
50-
"""
51-
52-
change_form_template = 'icekit/admin/fluent_layouts_change_form.html'
53-
54-
class Media:
55-
js = ('icekit/admin/js/fluent_layouts.js', )
56-
57-
def formfield_for_foreignkey(self, db_field, *args, **kwargs):
58-
"""
59-
Update queryset for ``layout`` field.
60-
"""
61-
formfield = super(FluentLayoutsMixin, self).formfield_for_foreignkey(
62-
db_field, *args, **kwargs)
63-
if db_field.name == 'layout':
64-
formfield.queryset = formfield.queryset.for_model(self.model)
65-
return formfield
66-
67-
def get_placeholder_data(self, request, obj):
68-
"""
69-
Get placeholder data from layout.
70-
"""
71-
if not obj or not obj.layout:
72-
data = [PlaceholderData(slot='main', role='m', title='Main')]
73-
else:
74-
data = obj.layout.get_placeholder_data()
75-
return data
76-
77-
7844
class ChildModelPluginPolymorphicParentModelAdmin(PolymorphicParentModelAdmin):
7945
"""
8046
Get child models and choice labels from registered plugins.

icekit/admin_mixins.py

Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,33 @@
1+
from fluent_contents.admin import PlaceholderEditorAdmin
2+
from fluent_contents.models import PlaceholderData
3+
4+
5+
class FluentLayoutsMixin(PlaceholderEditorAdmin):
6+
"""
7+
Mixin class for models that have a ``layout`` field and fluent content.
8+
"""
9+
10+
change_form_template = 'icekit/admin/fluent_layouts_change_form.html'
11+
12+
class Media:
13+
js = ('icekit/admin/js/fluent_layouts.js', )
14+
15+
def formfield_for_foreignkey(self, db_field, *args, **kwargs):
16+
"""
17+
Update queryset for ``layout`` field.
18+
"""
19+
formfield = super(FluentLayoutsMixin, self).formfield_for_foreignkey(
20+
db_field, *args, **kwargs)
21+
if db_field.name == 'layout':
22+
formfield.queryset = formfield.queryset.for_model(self.model)
23+
return formfield
24+
25+
def get_placeholder_data(self, request, obj):
26+
"""
27+
Get placeholder data from layout.
28+
"""
29+
if not obj or not obj.layout:
30+
data = [PlaceholderData(slot='main', role='m', title='Main')]
31+
else:
32+
data = obj.layout.get_placeholder_data()
33+
return data

icekit/articles/abstract_models.py

Lines changed: 2 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,6 @@
1-
from icekit.abstract_models import FluentFieldsMixin
2-
from icekit.publishing.models import PublishingModel
1+
from icekit.publishing.models import PublishableFluentContents
32
from django.db import models
43

5-
# TODO: this should ideally be in icekit.abstract_models, but doing so
6-
# creates circular import errors.
7-
class PublishableFluentModel(FluentFieldsMixin, PublishingModel):
8-
class Meta:
9-
abstract = True
104

115
class TitleSlugMixin(models.Model):
126
# TODO: this should perhaps become part of a wider ICEkit mixin that covers
@@ -22,12 +16,11 @@ def __unicode__(self):
2216
return self.title
2317

2418

25-
class PublishableArticle(PublishableFluentModel, TitleSlugMixin):
19+
class PublishableArticle(PublishableFluentContents, TitleSlugMixin):
2620
'''
2721
Basic Article type (ie that forms the basis of independent collections of
2822
publishable things).
2923
'''
3024

3125
class Meta:
3226
abstract = True
33-

icekit/articles/admin.py

Lines changed: 2 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -1,18 +1,11 @@
11
from django.contrib import admin
22

3-
from icekit.admin import FluentLayoutsMixin
4-
from icekit.publishing.admin import PublishingAdmin
5-
6-
class PublishableFluentModelAdmin(PublishingAdmin, FluentLayoutsMixin):
7-
"""
8-
Add publishing features for non-Page rich content models
9-
"""
10-
pass
3+
from icekit.publishing.admin import PublishableFluentContentsAdmin
114

125

136
class TitleSlugAdmin(admin.ModelAdmin):
147
prepopulated_fields = {"slug": ("title",)}
158

169

17-
class PublishableArticleAdmin(PublishableFluentModelAdmin, TitleSlugAdmin):
10+
class PublishableArticleAdmin(PublishableFluentContentsAdmin, TitleSlugAdmin):
1811
pass

icekit/management/commands/add_missing_placeholders.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
from django.apps import apps
22
from django.core.management.base import NoArgsCommand
33
from django.utils.encoding import force_text
4-
from icekit.abstract_models import FluentFieldsMixin
4+
from icekit.mixins import FluentFieldsMixin
55

66

77
class Command(NoArgsCommand):

0 commit comments

Comments
 (0)