Mercurial > piecrust2
comparison piecrust/rendering.py @ 515:16e705c58cae
internal: Improve handling of taxonomy term slugification.
This paves the way to bring slugification options like transliteration to
PieCrust. This change mostly makes sure we use one-way slugification, which
means, for serving/previewing, we need to slugify each page's terms to compare
to the stuff captured from the URL. It also simplifies things a bit in the
code.
author | Ludovic Chabant <ludovic@chabant.com> |
---|---|
date | Sun, 26 Jul 2015 23:16:15 -0700 |
parents | 7d868afc6791 |
children | bab91fcef741 |
comparison
equal
deleted
inserted
replaced
514:c9c305645e5f | 515:16e705c58cae |
---|---|
4 import logging | 4 import logging |
5 from werkzeug.utils import cached_property | 5 from werkzeug.utils import cached_property |
6 from piecrust.data.builder import ( | 6 from piecrust.data.builder import ( |
7 DataBuildingContext, build_page_data, build_layout_data) | 7 DataBuildingContext, build_page_data, build_layout_data) |
8 from piecrust.data.filters import ( | 8 from piecrust.data.filters import ( |
9 PaginationFilter, HasFilterClause, IsFilterClause, AndBooleanClause, | 9 PaginationFilter, SettingFilterClause, page_value_accessor) |
10 page_value_accessor) | |
11 from piecrust.sources.base import PageSource | 10 from piecrust.sources.base import PageSource |
12 from piecrust.templating.base import TemplateNotFoundError, TemplatingError | 11 from piecrust.templating.base import TemplateNotFoundError, TemplatingError |
13 | 12 |
14 | 13 |
15 logger = logging.getLogger(__name__) | 14 logger = logging.getLogger(__name__) |
165 self._raiseIfNoCurrentPass() | 164 self._raiseIfNoCurrentPass() |
166 if isinstance(source, PageSource): | 165 if isinstance(source, PageSource): |
167 pass_info = self.current_pass_info | 166 pass_info = self.current_pass_info |
168 pass_info.used_source_names.add(source.name) | 167 pass_info.used_source_names.add(source.name) |
169 | 168 |
170 def setTaxonomyFilter(self, taxonomy, term_value): | 169 def setTaxonomyFilter(self, term_value): |
170 if not self.page.route.is_taxonomy_route: | |
171 raise Exception("The page for this context is not tied to a " | |
172 "taxonomy route: %s" % self.uri) | |
173 | |
174 taxonomy = self.app.getTaxonomy(self.page.route.taxonomy_name) | |
175 flt = PaginationFilter(value_accessor=page_value_accessor) | |
176 flt.addClause(HasTaxonomyTermsFilterClause( | |
177 taxonomy, term_value, self.page.route.slugifyTaxonomyTerm)) | |
178 self.pagination_filter = flt | |
179 | |
171 is_combination = isinstance(term_value, tuple) | 180 is_combination = isinstance(term_value, tuple) |
172 flt = PaginationFilter(value_accessor=page_value_accessor) | |
173 if taxonomy.is_multiple: | |
174 if is_combination: | |
175 abc = AndBooleanClause() | |
176 for t in term_value: | |
177 abc.addClause(HasFilterClause(taxonomy.setting_name, t)) | |
178 flt.addClause(abc) | |
179 else: | |
180 flt.addClause( | |
181 HasFilterClause(taxonomy.setting_name, term_value)) | |
182 else: | |
183 flt.addClause(IsFilterClause(taxonomy.setting_name, term_value)) | |
184 self.pagination_filter = flt | |
185 | |
186 self.custom_data = { | 181 self.custom_data = { |
187 taxonomy.term_name: term_value, | 182 taxonomy.term_name: term_value, |
188 'is_multiple_%s' % taxonomy.term_name: is_combination} | 183 'is_multiple_%s' % taxonomy.term_name: is_combination} |
189 | 184 |
190 def _raiseIfNoCurrentPass(self): | 185 def _raiseIfNoCurrentPass(self): |
191 if self._current_pass == PASS_NONE: | 186 if self._current_pass == PASS_NONE: |
192 raise Exception("No rendering pass is currently active.") | 187 raise Exception("No rendering pass is currently active.") |
188 | |
189 | |
190 class HasTaxonomyTermsFilterClause(SettingFilterClause): | |
191 def __init__(self, taxonomy, value, slugifier): | |
192 super(HasTaxonomyTermsFilterClause, self).__init__( | |
193 taxonomy.setting_name, value) | |
194 self._taxonomy = taxonomy | |
195 self._slugifier = slugifier | |
196 self._is_combination = isinstance(self.value, tuple) | |
197 | |
198 def pageMatches(self, fil, page): | |
199 if self._taxonomy.is_multiple: | |
200 # Multiple taxonomy, i.e. it supports multiple terms, like tags. | |
201 page_values = fil.value_accessor(page, self.name) | |
202 if page_values is None or not isinstance(page_values, list): | |
203 return False | |
204 | |
205 if self._slugifier is not None: | |
206 page_set = set(map(self._slugifier, page_values)) | |
207 else: | |
208 page_set = set(page_values) | |
209 | |
210 if self._is_combination: | |
211 # Multiple taxonomy, and multiple terms to match. Check that | |
212 # the ones to match are all in the page's terms. | |
213 value_set = set(self.value) | |
214 return value_set.issubset(page_set) | |
215 else: | |
216 # Multiple taxonomy, one term to match. | |
217 return self.value in page_set | |
218 | |
219 # Single taxonomy. Just compare the values. | |
220 page_value = fil.value_accessor(page, self.name) | |
221 if page_value is None: | |
222 return False | |
223 if self._slugifier is not None: | |
224 page_value = self._slugifier(page_value) | |
225 return page_value == self.value | |
193 | 226 |
194 | 227 |
195 def render_page(ctx): | 228 def render_page(ctx): |
196 eis = ctx.app.env.exec_info_stack | 229 eis = ctx.app.env.exec_info_stack |
197 eis.pushPage(ctx.page, ctx) | 230 eis.pushPage(ctx.page, ctx) |