misc: allow template URLs in feed and json cells (#15423)
This commit is contained in:
parent
c6b4b5b6bd
commit
a72c25dd59
|
@ -18,6 +18,9 @@
|
||||||
|
|
||||||
from django import forms
|
from django import forms
|
||||||
from django.conf import settings
|
from django.conf import settings
|
||||||
|
from django.core import validators
|
||||||
|
from django.forms.widgets import TextInput
|
||||||
|
from django.utils.encoding import force_text
|
||||||
|
|
||||||
import ckeditor.fields
|
import ckeditor.fields
|
||||||
|
|
||||||
|
@ -48,3 +51,22 @@ class RichTextFormField(ckeditor.fields.RichTextFormField):
|
||||||
value = value.replace(u' !', u'\u202f!')
|
value = value.replace(u' !', u'\u202f!')
|
||||||
value = value.replace(u' ?', u'\u202f?')
|
value = value.replace(u' ?', u'\u202f?')
|
||||||
return value
|
return value
|
||||||
|
|
||||||
|
|
||||||
|
def templatable_url_validator(value):
|
||||||
|
value = force_text(value)
|
||||||
|
if '{{' in value or '{%' in value:
|
||||||
|
# leave templates alone
|
||||||
|
return
|
||||||
|
validators.URLValidator()(value)
|
||||||
|
|
||||||
|
|
||||||
|
class TemplatableURLField(forms.URLField):
|
||||||
|
widget = TextInput
|
||||||
|
default_validators = [templatable_url_validator]
|
||||||
|
|
||||||
|
def to_python(self, value):
|
||||||
|
value = super(forms.URLField, self).to_python(value)
|
||||||
|
if '{{' in value or '{%' in value:
|
||||||
|
return value
|
||||||
|
return super(TemplatableURLField, self).to_python(value)
|
||||||
|
|
|
@ -0,0 +1,25 @@
|
||||||
|
# -*- coding: utf-8 -*-
|
||||||
|
# Generated by Django 1.11.12 on 2019-07-01 19:18
|
||||||
|
from __future__ import unicode_literals
|
||||||
|
|
||||||
|
from django.db import migrations, models
|
||||||
|
|
||||||
|
|
||||||
|
class Migration(migrations.Migration):
|
||||||
|
|
||||||
|
dependencies = [
|
||||||
|
('data', '0036_page_sub_slug'),
|
||||||
|
]
|
||||||
|
|
||||||
|
operations = [
|
||||||
|
migrations.AlterField(
|
||||||
|
model_name='feedcell',
|
||||||
|
name='url',
|
||||||
|
field=models.CharField(blank=True, max_length=200, verbose_name='URL'),
|
||||||
|
),
|
||||||
|
migrations.AlterField(
|
||||||
|
model_name='jsoncell',
|
||||||
|
name='url',
|
||||||
|
field=models.CharField(blank=True, max_length=200, verbose_name='URL'),
|
||||||
|
),
|
||||||
|
]
|
|
@ -50,7 +50,7 @@ from django.forms.widgets import MediaDefiningClass
|
||||||
from django.template import Context, engines, TemplateDoesNotExist
|
from django.template import Context, engines, TemplateDoesNotExist
|
||||||
from django.test.client import RequestFactory
|
from django.test.client import RequestFactory
|
||||||
|
|
||||||
from .fields import RichTextField
|
from .fields import RichTextField, TemplatableURLField
|
||||||
|
|
||||||
from jsonfield import JSONField
|
from jsonfield import JSONField
|
||||||
|
|
||||||
|
@ -505,9 +505,11 @@ class CellBase(six.with_metaclass(CellMeta, models.Model)):
|
||||||
last_update_timestamp = models.DateTimeField(auto_now=True)
|
last_update_timestamp = models.DateTimeField(auto_now=True)
|
||||||
|
|
||||||
default_form_class = None
|
default_form_class = None
|
||||||
|
manager_form_factory_kwargs = {}
|
||||||
|
manager_form_template = 'combo/cell_form.html'
|
||||||
|
|
||||||
visible = True
|
visible = True
|
||||||
user_dependant = False
|
user_dependant = False
|
||||||
manager_form_template = 'combo/cell_form.html'
|
|
||||||
template_name = None
|
template_name = None
|
||||||
|
|
||||||
# get_badge(self, context); set to None so cell types can be skipped easily
|
# get_badge(self, context); set to None so cell types can be skipped easily
|
||||||
|
@ -658,7 +660,7 @@ class CellBase(six.with_metaclass(CellMeta, models.Model)):
|
||||||
if not fields:
|
if not fields:
|
||||||
return None
|
return None
|
||||||
|
|
||||||
return model_forms.modelform_factory(self.__class__, fields=fields)
|
return model_forms.modelform_factory(self.__class__, fields=fields, **self.manager_form_factory_kwargs)
|
||||||
|
|
||||||
def get_options_form_class(self):
|
def get_options_form_class(self):
|
||||||
return model_forms.modelform_factory(self.__class__,
|
return model_forms.modelform_factory(self.__class__,
|
||||||
|
@ -907,10 +909,11 @@ class LinkCell(CellBase):
|
||||||
@register_cell_class
|
@register_cell_class
|
||||||
class FeedCell(CellBase):
|
class FeedCell(CellBase):
|
||||||
title = models.CharField(_('Title'), max_length=150, blank=True)
|
title = models.CharField(_('Title'), max_length=150, blank=True)
|
||||||
url = models.URLField(_('URL'), blank=True)
|
url = models.CharField(_('URL'), blank=True, max_length=200)
|
||||||
limit = models.PositiveSmallIntegerField(_('Maximum number of entries'),
|
limit = models.PositiveSmallIntegerField(_('Maximum number of entries'),
|
||||||
null=True, blank=True)
|
null=True, blank=True)
|
||||||
|
|
||||||
|
manager_form_factory_kwargs = {'field_classes': {'url': TemplatableURLField}}
|
||||||
template_name = 'combo/feed-cell.html'
|
template_name = 'combo/feed-cell.html'
|
||||||
|
|
||||||
class Meta:
|
class Meta:
|
||||||
|
@ -1275,7 +1278,7 @@ class JsonCellBase(CellBase):
|
||||||
@register_cell_class
|
@register_cell_class
|
||||||
class JsonCell(JsonCellBase):
|
class JsonCell(JsonCellBase):
|
||||||
title = models.CharField(_('Title'), max_length=150, blank=True)
|
title = models.CharField(_('Title'), max_length=150, blank=True)
|
||||||
url = models.URLField(_('URL'), blank=True)
|
url = models.CharField(_('URL'), blank=True, max_length=200)
|
||||||
template_string = models.TextField(_('Display Template'), blank=True, null=True)
|
template_string = models.TextField(_('Display Template'), blank=True, null=True)
|
||||||
cache_duration = models.PositiveIntegerField(
|
cache_duration = models.PositiveIntegerField(
|
||||||
_('Cache duration'), default=60)
|
_('Cache duration'), default=60)
|
||||||
|
@ -1287,6 +1290,8 @@ class JsonCell(JsonCellBase):
|
||||||
timeout = models.PositiveIntegerField(_('Request timeout'), default=0,
|
timeout = models.PositiveIntegerField(_('Request timeout'), default=0,
|
||||||
help_text=_('In seconds. Use 0 for default system timeout'))
|
help_text=_('In seconds. Use 0 for default system timeout'))
|
||||||
|
|
||||||
|
manager_form_factory_kwargs = {'field_classes': {'url': TemplatableURLField}}
|
||||||
|
|
||||||
class Meta:
|
class Meta:
|
||||||
verbose_name = _('JSON Prototype')
|
verbose_name = _('JSON Prototype')
|
||||||
|
|
||||||
|
|
|
@ -586,6 +586,38 @@ def test_edit_text_cell(app, admin_user):
|
||||||
assert TextCell.objects.get(id=cells[0].id).text == u'Hello\u00a0: World'
|
assert TextCell.objects.get(id=cells[0].id).text == u'Hello\u00a0: World'
|
||||||
|
|
||||||
|
|
||||||
|
def test_edit_json_cell(app, admin_user):
|
||||||
|
Page.objects.all().delete()
|
||||||
|
page = Page(title='One', slug='one', template_name='standard')
|
||||||
|
page.save()
|
||||||
|
|
||||||
|
app = login(app)
|
||||||
|
resp = app.get('/manage/pages/%s/' % page.id)
|
||||||
|
data_add_url = [x for x in resp.html.find_all('option') if x.text == 'JSON Prototype'][0].get('data-add-url')
|
||||||
|
resp = app.get(data_add_url)
|
||||||
|
|
||||||
|
cells = CellBase.get_cells(page_id=page.id)
|
||||||
|
assert len(cells) == 1
|
||||||
|
assert isinstance(cells[0], JsonCell)
|
||||||
|
assert resp.location.endswith('/manage/pages/%s/#cell-%s' % (page.id, cells[0].get_reference()))
|
||||||
|
|
||||||
|
resp = app.get('/manage/pages/%s/' % page.id)
|
||||||
|
resp.form['cdata_jsoncell-%s-url' % cells[0].id].value = 'xxx'
|
||||||
|
resp = resp.form.submit()
|
||||||
|
assert 'Enter a valid URL.' in resp.text
|
||||||
|
assert JsonCell.objects.get(id=cells[0].id).url == ''
|
||||||
|
|
||||||
|
resp = app.get('/manage/pages/%s/' % page.id)
|
||||||
|
resp.form['cdata_jsoncell-%s-url' % cells[0].id].value = 'https://www.example.net/'
|
||||||
|
resp = resp.form.submit()
|
||||||
|
assert JsonCell.objects.get(id=cells[0].id).url == 'https://www.example.net/'
|
||||||
|
|
||||||
|
resp = app.get('/manage/pages/%s/' % page.id)
|
||||||
|
resp.form['cdata_jsoncell-%s-url' % cells[0].id].value = '{{url}}'
|
||||||
|
resp = resp.form.submit()
|
||||||
|
assert JsonCell.objects.get(id=cells[0].id).url == '{{url}}'
|
||||||
|
|
||||||
|
|
||||||
def test_edit_config_json_cell(app, admin_user):
|
def test_edit_config_json_cell(app, admin_user):
|
||||||
Page.objects.all().delete()
|
Page.objects.all().delete()
|
||||||
page = Page(title='One', slug='one', template_name='standard')
|
page = Page(title='One', slug='one', template_name='standard')
|
||||||
|
|
Loading…
Reference in New Issue