general: add a 'base.html' template webservice (#7137)
This commit is contained in:
parent
038d00a6de
commit
4de32236f0
|
@ -131,6 +131,7 @@ class WcsCategoryCell(WcsCommonCategoryCell):
|
|||
|
||||
class WcsBlurpMixin(object):
|
||||
is_enabled = classmethod(is_wcs_enabled)
|
||||
user_dependant = True
|
||||
|
||||
def get_blurp_renderer(self, context):
|
||||
if self.wcs_site:
|
||||
|
|
|
@ -76,15 +76,19 @@ class Page(models.Model):
|
|||
self.order = max_order + 1
|
||||
return super(Page, self).save(*args, **kwargs)
|
||||
|
||||
def get_online_url(self):
|
||||
parts = [self.slug]
|
||||
def get_parents_and_self(self):
|
||||
pages = [self]
|
||||
page = self
|
||||
while page.parent_id:
|
||||
page = page.parent
|
||||
parts.append(page.slug)
|
||||
pages.append(page)
|
||||
return reversed(pages)
|
||||
|
||||
def get_online_url(self):
|
||||
parts = [x.slug for x in self.get_parents_and_self()]
|
||||
if parts == ['index']:
|
||||
return '/'
|
||||
return '/' + '/'.join(reversed(parts))
|
||||
return '/' + '/'.join(parts)
|
||||
|
||||
def get_page_of_level(self, level):
|
||||
'''Return page of given level in the page hierarchy.'''
|
||||
|
@ -212,6 +216,7 @@ class CellBase(models.Model):
|
|||
|
||||
default_form_class = None
|
||||
visible = True
|
||||
user_dependant = False
|
||||
|
||||
class Meta:
|
||||
abstract = True
|
||||
|
@ -319,6 +324,10 @@ class CellBase(models.Model):
|
|||
context.'''
|
||||
return True
|
||||
|
||||
def is_user_dependant(self, context):
|
||||
'''Return whether the cell content varies from user to user.'''
|
||||
return self.user_dependant
|
||||
|
||||
|
||||
@register_cell_class
|
||||
class TextCell(CellBase):
|
||||
|
|
|
@ -1,14 +1,24 @@
|
|||
function combo_load_cell(elem, url) {
|
||||
$.ajax({url: url,
|
||||
xhrFields: { withCredentials: true },
|
||||
async: true,
|
||||
dataType: 'html',
|
||||
crossDomain: true,
|
||||
success: function(data) { $(elem).replaceWith(data); },
|
||||
error: function(error) { console.log(':(', error); }
|
||||
});
|
||||
}
|
||||
|
||||
$(function() {
|
||||
$('[data-ajax-cell-refresh]').each(function(idx, elem) {
|
||||
var $elem = $(elem);
|
||||
function refresh() {
|
||||
$elem.find('> div').load($elem.data('ajax-cell-url'));
|
||||
combo_load_cell($elem.find('> div'), $elem.data('ajax-cell-url'));
|
||||
}
|
||||
$elem.timeout_id = setInterval(refresh, $elem.data('ajax-cell-refresh')*1000);
|
||||
});
|
||||
$('[data-ajax-cell-must-load]').each(function(idx, elem) {
|
||||
var $elem = $(elem);
|
||||
console.log('loading:', $elem.parents('div.cell').data('ajax-cell-url'));
|
||||
$elem.load($elem.parents('div.cell').data('ajax-cell-url'));
|
||||
combo_load_cell($elem, $elem.parents('div.cell').data('ajax-cell-url'));
|
||||
});
|
||||
});
|
||||
|
|
|
@ -3,7 +3,7 @@
|
|||
<ul>
|
||||
{% for menuitem in menuitems %}
|
||||
<li class="menu-{{ menuitem.page.slug }} {% if menuitem.selected %}selected{% endif %}"><a
|
||||
href="{{ menuitem.page.get_online_url }}">{{ menuitem.page.title }}</a>
|
||||
href="{% page_absolute_url menuitem.page %}">{{ menuitem.page.title }}</a>
|
||||
{% if depth > 1 %}
|
||||
{% show_menu current_page=menuitem.page level=-1 depth=depth reduce_depth=True %}
|
||||
{% endif %}
|
||||
|
|
|
@ -1,8 +1,11 @@
|
|||
{% load combo %}
|
||||
{% for cell in cells %}
|
||||
<div class="cell {{ cell.css_class_name }} {% if cell.slug %}{{cell.slug}}{% endif %}"
|
||||
data-ajax-cell-url="{% url 'combo-public-ajax-page-cell' page_pk=page.id cell_reference=cell.get_reference %}"
|
||||
data-ajax-cell-url="{{ site_base }}{% url 'combo-public-ajax-page-cell' page_pk=cell.page.id cell_reference=cell.get_reference %}"
|
||||
{% if cell.ajax_refresh %}
|
||||
data-ajax-cell-refresh="{{ cell.ajax_refresh }}"
|
||||
{% endif %}><div>{% render_cell cell %}</div></div>
|
||||
{% endfor %}
|
||||
{% if render_skeleton %}
|
||||
{{ skeleton }}
|
||||
{% endif %}
|
||||
|
|
|
@ -26,19 +26,35 @@ from combo.utils import NothingInCacheException
|
|||
|
||||
register = template.Library()
|
||||
|
||||
def skeleton_text(context, placeholder_name):
|
||||
if context['request'].GET.get('format') == 'ezt':
|
||||
return '[if-any %s][%s][end]' % (placeholder_name, placeholder_name)
|
||||
return '{%% block %s %%}{%% endblock %%}' % placeholder_name
|
||||
|
||||
@register.inclusion_tag('combo/placeholder.html', takes_context=True)
|
||||
def placeholder(context, placeholder_name):
|
||||
context['cells'] = [x for x in context['page_cells'] if
|
||||
x.placeholder == placeholder_name and x.is_relevant(context)]
|
||||
x.placeholder == placeholder_name and
|
||||
(context.get('render_skeleton') or x.is_relevant(context))]
|
||||
if context.get('render_skeleton') and not context['cells']:
|
||||
context['skeleton'] = skeleton_text(context, placeholder_name)
|
||||
return context
|
||||
|
||||
@register.simple_tag(takes_context=True)
|
||||
def render_cell(context, cell):
|
||||
if context.get('render_skeleton') and cell.is_user_dependant(context):
|
||||
return template.loader.get_template('combo/deferred-cell.html').render(context)
|
||||
try:
|
||||
return cell.render(context)
|
||||
except NothingInCacheException:
|
||||
return template.loader.get_template('combo/deferred-cell.html').render(context)
|
||||
|
||||
@register.simple_tag(takes_context=True)
|
||||
def skeleton_extra_placeholder(context, placeholder_name):
|
||||
if context.get('render_skeleton'):
|
||||
return skeleton_text(context, placeholder_name)
|
||||
return ''
|
||||
|
||||
@register.inclusion_tag('combo/menu.html', takes_context=True)
|
||||
def show_menu(context, level=0, current_page=None, depth=1, reduce_depth=False):
|
||||
if reduce_depth:
|
||||
|
@ -49,6 +65,10 @@ def show_menu(context, level=0, current_page=None, depth=1, reduce_depth=False):
|
|||
return get_menu_context(new_context, level=level, current_page=current_page,
|
||||
depth=depth)
|
||||
|
||||
@register.simple_tag(takes_context=True)
|
||||
def page_absolute_url(context, page):
|
||||
return context['request'].build_absolute_uri(page.get_online_url())
|
||||
|
||||
@register.filter(name='strptime')
|
||||
def strptime(date_string, date_format):
|
||||
try:
|
||||
|
|
|
@ -21,5 +21,6 @@ from . import views
|
|||
urlpatterns = patterns('combo.publicviews',
|
||||
url(r'^ajax/cell/(?P<page_pk>\w+)/(?P<cell_reference>[\w_-]+)/$',
|
||||
views.ajax_page_cell, name='combo-public-ajax-page-cell'),
|
||||
(r'__skeleton__/$', views.skeleton),
|
||||
(r'', views.page),
|
||||
)
|
||||
|
|
|
@ -15,6 +15,7 @@
|
|||
# along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
import urllib
|
||||
import urlparse
|
||||
|
||||
from django.conf import settings
|
||||
from django.contrib.auth import logout as auth_logout
|
||||
|
@ -67,11 +68,79 @@ def ajax_page_cell(request, page_pk, cell_reference):
|
|||
'page': page,
|
||||
'request': request,
|
||||
'ajax': True,
|
||||
'site_base': request.build_absolute_uri('/')[:-1],
|
||||
})
|
||||
|
||||
return HttpResponse(cell.render(context), content_type='text/html')
|
||||
|
||||
|
||||
def extend_with_locked_placeholders_cells(cells, page, pages):
|
||||
locked_placeholders = page.get_locked_placeholders(cells)
|
||||
|
||||
if locked_placeholders:
|
||||
# there are some acquired placeholders, look in parent pages for
|
||||
# appropriate content.
|
||||
try:
|
||||
# add the site index page as ultimate parent
|
||||
pages.insert(0, Page.objects.get(slug='index'))
|
||||
except Page.DoesNotExist:
|
||||
pass
|
||||
unlocker_cells = CellBase.get_cells(page_id__in=[x.id for x in pages])
|
||||
found_placeholders = {}
|
||||
for parent_page in reversed(pages[:-1]):
|
||||
for placeholder in parent_page.get_unlocked_placeholders(unlocker_cells):
|
||||
if not placeholder in locked_placeholders:
|
||||
continue
|
||||
if not placeholder in found_placeholders:
|
||||
found_placeholders[placeholder] = parent_page.id
|
||||
if len(found_placeholders) == len(locked_placeholders):
|
||||
break
|
||||
|
||||
# add found cells to the page cells
|
||||
for placeholder_key, page_id in found_placeholders.items():
|
||||
cells.extend([x for x in unlocker_cells if x.page_id == page_id and
|
||||
x.placeholder == placeholder_key])
|
||||
|
||||
|
||||
def skeleton(request):
|
||||
source = request.GET['source']
|
||||
selected_page = None
|
||||
|
||||
# look in redirect pages after the best match for the source
|
||||
redirect_pages = Page.objects.exclude(redirect_url__isnull=True).exclude(redirect_url='')
|
||||
for page in redirect_pages:
|
||||
if source.startswith(page.redirect_url):
|
||||
if selected_page is None or len(page.redirect_url) > len(selected_page.redirect_url):
|
||||
selected_page = page
|
||||
|
||||
if selected_page is None:
|
||||
# if there was no page found, look for a domain match
|
||||
netloc = urlparse.urlparse(source).netloc
|
||||
for page in redirect_pages:
|
||||
if urlparse.urlparse(page.redirect_url).netloc == netloc:
|
||||
selected_page = page
|
||||
break
|
||||
else:
|
||||
raise PermissionDenied()
|
||||
|
||||
pages = list(page.get_parents_and_self())
|
||||
cells = CellBase.get_cells(page_id=page.id)
|
||||
extend_with_locked_placeholders_cells(cells, page, pages)
|
||||
|
||||
combo_template = settings.COMBO_PUBLIC_TEMPLATES[page.template_name]
|
||||
|
||||
ctx = {
|
||||
'page': page,
|
||||
'page_cells': cells,
|
||||
'request': request,
|
||||
'render_skeleton': True,
|
||||
'site_base': request.build_absolute_uri('/')[:-1],
|
||||
}
|
||||
|
||||
template_name = combo_template['template']
|
||||
return render(request, template_name, ctx)
|
||||
|
||||
|
||||
def page(request):
|
||||
url = request.path_info
|
||||
parts = [x for x in request.path_info.strip('/').split('/') if x]
|
||||
|
@ -102,32 +171,7 @@ def page(request):
|
|||
combo_template = settings.COMBO_PUBLIC_TEMPLATES[page.template_name]
|
||||
|
||||
cells = CellBase.get_cells(page_id=page.id)
|
||||
locked_placeholders = page.get_locked_placeholders(cells)
|
||||
|
||||
if locked_placeholders:
|
||||
# there are some acquired placeholders, look in parent pages for
|
||||
# appropriate content.
|
||||
try:
|
||||
# add the site index page as ultimate parent
|
||||
pages.insert(0, Page.objects.get(slug='index'))
|
||||
except Page.DoesNotExist:
|
||||
pass
|
||||
unlocker_cells = CellBase.get_cells(page_id__in=[x.id for x in pages])
|
||||
found_placeholders = {}
|
||||
for parent_page in reversed(pages[:-1]):
|
||||
for placeholder in parent_page.get_unlocked_placeholders(unlocker_cells):
|
||||
if not placeholder in locked_placeholders:
|
||||
continue
|
||||
if not placeholder in found_placeholders:
|
||||
found_placeholders[placeholder] = parent_page.id
|
||||
if len(found_placeholders) == len(locked_placeholders):
|
||||
break
|
||||
|
||||
# add found cells to the page cells
|
||||
for placeholder_key, page_id in found_placeholders.items():
|
||||
cells.extend([x for x in unlocker_cells if x.page_id == page_id and
|
||||
x.placeholder == placeholder_key])
|
||||
|
||||
extend_with_locked_placeholders_cells(cells, page, pages)
|
||||
cells = [x for x in cells if x.is_visible(user=request.user)]
|
||||
|
||||
ctx = {
|
||||
|
|
|
@ -1,5 +1,6 @@
|
|||
from webtest import TestApp
|
||||
import pytest
|
||||
import urllib
|
||||
|
||||
from combo.wsgi import application
|
||||
from combo.data.models import Page, CellBase, TextCell
|
||||
|
@ -69,3 +70,31 @@ def test_page_private_logged_in(admin_user):
|
|||
page.save()
|
||||
app = login(TestApp(application))
|
||||
resp = app.get('/', status=200)
|
||||
|
||||
def test_page_skeleton():
|
||||
Page.objects.all().delete()
|
||||
page = Page(title='Elsewhere', slug='elsewhere', template_name='standard',
|
||||
redirect_url='http://example.net/foo/')
|
||||
page.save()
|
||||
app = TestApp(application)
|
||||
|
||||
# url prefix match
|
||||
resp = app.get('/__skeleton__/?source=%s' % urllib.quote('http://example.net/foo/bar'))
|
||||
assert '{% block content %}{% endblock %}' in resp.body
|
||||
assert '{% block footer %}{% endblock %}' in resp.body
|
||||
|
||||
# url netloc match
|
||||
resp = app.get('/__skeleton__/?source=%s' % urllib.quote('http://example.net'))
|
||||
assert '{% block content %}{% endblock %}' in resp.body
|
||||
assert '{% block footer %}{% endblock %}' in resp.body
|
||||
|
||||
# no match
|
||||
resp = app.get('/__skeleton__/?source=%s' % urllib.quote('http://example.com/foo/bar'), status=403)
|
||||
|
||||
# check with a footer cell
|
||||
cell = TextCell(page=page, placeholder='footer', text='Foobar', order=0)
|
||||
cell.save()
|
||||
resp = app.get('/__skeleton__/?source=%s' % urllib.quote('http://example.net'))
|
||||
assert '{% block content %}{% endblock %}' in resp.body
|
||||
assert not '{% block footer %}{% endblock %}' in resp.body
|
||||
assert 'Foobar' in resp.body
|
||||
|
|
Loading…
Reference in New Issue