|
5 | 5 | # Compose concrete models from abstract models and mixins, to facilitate reuse. |
6 | 6 | from django.contrib.contenttypes.models import ContentType |
7 | 7 | from django.db import models |
8 | | -from django.template.defaultfilters import striptags |
9 | 8 | from django.template.loader import get_template |
10 | 9 | from django.utils import encoding, timezone |
11 | 10 | from django.utils.translation import ugettext_lazy as _ |
12 | 11 | 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 |
19 | 12 |
|
20 | 13 | from . import fields, plugins |
21 | 14 |
|
22 | 15 |
|
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 | | - |
124 | 16 | class AbstractBaseModel(models.Model): |
125 | 17 | """ |
126 | 18 | Abstract base model. |
|
0 commit comments