wcs: card cell & multiple card identifiers (#58862)
gitea-wip/combo/pipeline/head There was a failure building this commit Details
gitea/combo/pipeline/head Something is wrong with the build of this commit Details

This commit is contained in:
Lauréline Guérin 2021-11-23 16:57:01 +01:00
parent 09c30d619c
commit 39c7114cf7
No known key found for this signature in database
GPG Key ID: 1FAB9B9B4F93D473
6 changed files with 175 additions and 48 deletions

View File

@ -71,7 +71,7 @@ class WcsCardInfoCellForm(forms.ModelForm):
class Meta:
model = WcsCardInfosCell
fields = ('carddef_reference', 'title_type', 'custom_title', 'card_id', 'custom_schema')
fields = ('carddef_reference', 'title_type', 'custom_title', 'card_ids', 'custom_schema')
widgets = {
'custom_schema': forms.HiddenInput(),
}

View File

@ -0,0 +1,21 @@
from django.db import migrations, models
class Migration(migrations.Migration):
dependencies = [
('wcs', '0042_current_forms_custom_title'),
]
operations = [
migrations.RenameField(
model_name='wcscardinfoscell',
old_name='card_id',
new_name='card_ids',
),
migrations.AlterField(
model_name='wcscardinfoscell',
name='card_ids',
field=models.CharField(blank=True, max_length=1000, verbose_name='Card Identifiers'),
),
]

View File

@ -24,7 +24,7 @@ from django.contrib.postgres.fields import JSONField
from django.db import models
from django.forms import Select
from django.forms import models as model_forms
from django.template import Context, Template, TemplateSyntaxError, VariableDoesNotExist
from django.template import Context, RequestContext, Template, TemplateSyntaxError, VariableDoesNotExist
from django.utils.safestring import mark_safe
from django.utils.text import slugify
from django.utils.translation import ugettext_lazy as _
@ -899,7 +899,7 @@ class WcsCardsCell(CardMixin, WcsBlurpMixin, CellBase):
@register_cell_class
class WcsCardInfosCell(CardMixin, CellBase):
carddef_reference = models.CharField(_('Card Model'), max_length=150)
card_id = models.CharField(_('Card Identifier'), max_length=1000, blank=True)
card_ids = models.CharField(_('Card Identifiers'), max_length=1000, blank=True)
without_user = models.BooleanField(_('Ignore the logged-in user'), default=False)
custom_schema = JSONField(blank=True, default=dict)
@ -961,16 +961,39 @@ class WcsCardInfosCell(CardMixin, CellBase):
populate_cache()
def get_card_id(self, context):
if self.card_id:
@property
def global_context_key(self):
return '%s-card-ids' % self.get_reference()
def modify_global_context(self, context, request):
if self.global_context_key not in context:
card_ids = self.get_card_ids(context, request)
context[self.global_context_key] = card_ids
def get_repeat_template(self, context):
return len(context[self.global_context_key])
def get_card_ids(self, original_context, request):
if self.card_ids:
try:
return Template(self.card_id).render(Context(context))
context = RequestContext(request)
context.push(original_context)
ids = Template(self.card_ids).render(context).split(',')
return [i.strip() for i in ids if i.strip()]
except (VariableDoesNotExist, TemplateSyntaxError):
return None
return []
card_slug = self.carddef_reference.split(':')[1]
card_id = '%s_id' % card_slug
return context.get(card_id) or None
if original_context.get(card_id):
return [original_context[card_id]]
return []
def get_card_id(self, context):
repeat_index = getattr(self, 'repeat_index', context.get('repeat_index'))
if repeat_index is not None:
return context[self.global_context_key][repeat_index]
return None
def get_extra_manager_context(self):
extra_context = super().get_extra_manager_context()
@ -992,7 +1015,7 @@ class WcsCardInfosCell(CardMixin, CellBase):
card_id = self.get_card_id(context)
if not card_id:
if self.card_id: # template defined, but result is empty or None
if self.card_ids: # template defined, but result is empty or None
extra_context['card_not_found'] = True
return extra_context
card_slug = self.carddef_reference.split(':')[1]

View File

@ -2110,8 +2110,7 @@ class ConfigJsonCell(JsonCellBase):
def make_global(self):
return settings.JSON_CELL_TYPES[self.key].get('make_global', False)
@property
def repeat(self):
def get_repeat_template(self, context):
return settings.JSON_CELL_TYPES[self.key].get('repeat')
@property

View File

@ -108,8 +108,8 @@ def placeholder(context, placeholder_name, **options):
context['skeleton'] = ''
if not context.get('placeholder_search_mode'):
for cell in [x for x in context['cells'] if hasattr(x, 'repeat')]:
repeat_template = cell.repeat
for cell in [x for x in context['cells'] if hasattr(x, 'get_repeat_template')]:
repeat_template = cell.get_repeat_template(context)
if not repeat_template:
continue

View File

@ -21,7 +21,6 @@ from requests.models import Response
from combo.apps.search.engines import engines
from combo.apps.search.models import SearchCell
from combo.apps.search.utils import index_site, search_site
from combo.apps.wcs.context_processors import Cards
from combo.apps.wcs.models import (
BackofficeSubmissionCell,
CategoriesCell,
@ -1616,7 +1615,6 @@ def test_cards_cell_render_user(mock_send, context, nocache):
cell.carddef_reference = 'default:card_model_1'
cell.save()
context['card_model_1_id'] = 11
context['synchronous'] = True # to get fresh content
assert context['request'].user is None
@ -1828,6 +1826,9 @@ def test_card_cell_render(mock_send, context):
assert '<p>Unknown Card</p>' in result
context['card_model_1_id'] = 11
request = RequestFactory().get('/')
cell.modify_global_context(context, request)
cell.repeat_index = 0
# query should fail as nothing is cached
cache.clear()
@ -1897,6 +1898,9 @@ def test_card_cell_render_text_field(mock_send, context):
cell.save()
context['card_model_1_id'] = 11
request = RequestFactory().get('/')
cell.modify_global_context(context, request)
cell.repeat_index = 0
context['synchronous'] = True # to get fresh content
result = cell.render(context)
@ -1927,6 +1931,9 @@ def test_card_cell_render_email_field(mock_send, context):
cell.save()
context['card_model_1_id'] = 11
request = RequestFactory().get('/')
cell.modify_global_context(context, request)
cell.repeat_index = 0
context['synchronous'] = True # to get fresh content
result = cell.render(context)
@ -1952,6 +1959,9 @@ def test_card_cell_render_custom_schema(mock_send, context):
cell.save()
context['card_model_1_id'] = 11
request = RequestFactory().get('/')
cell.modify_global_context(context, request)
cell.repeat_index = 0
context['synchronous'] = True # to get fresh content
result = cell.render(context)
@ -1994,58 +2004,128 @@ def test_card_cell_render_custom_schema(mock_send, context):
@mock.patch('combo.apps.wcs.utils.requests.send', side_effect=mocked_requests_send)
def test_card_cell_render_identifier(mock_send, context, nocache):
page = Page.objects.create(title='xxx', template_name='standard')
def test_card_cell_render_identifier(mock_send, nocache, app):
page = Page.objects.create(
title='xxx', slug='foo', template_name='standard', sub_slug='(?P<card_model_1_id>[a-z0-9]+)'
)
cell = WcsCardInfosCell(page=page, placeholder='content', order=0)
cell.carddef_reference = 'default:card_model_1'
cell.save()
context['card_model_1_id'] = 11
context['synchronous'] = True # to get fresh content
cell_url = reverse(
'combo-public-ajax-page-cell',
kwargs={'page_pk': page.pk, 'cell_reference': cell.get_reference()},
)
# check url called
mock_send.reset_mock()
result = cell.render(context)
resp = app.get(page.get_online_url() + '11/')
assert len(resp.context['cells']) == 1
assert resp.context['cells'][0].pk == cell.pk
assert resp.context['cells'][0].repeat_index == 0
extra_ctx = re.findall(r'data-extra-context="(.*)"', resp.text)
cell_resp = app.get(cell_url + '?ctx=' + extra_ctx[0])
assert cell_resp.context['repeat_index'] == 0
assert 'Card Model 1' in cell_resp
assert '<p>Unknown Card</p>' not in cell_resp
assert len(mock_send.call_args_list) == 1
assert '/api/cards/card_model_1/11/' in mock_send.call_args_list[0][0][0].url
assert 'Card Model 1' in result
assert '<p>Unknown Card</p>' not in result
# with identifier
cell.card_id = '42'
# with identifiers
page.sub_slug = ''
page.save()
cell.card_ids = '42'
cell.save()
mock_send.reset_mock()
result = cell.render(context)
resp = app.get(page.get_online_url())
assert len(resp.context['cells']) == 1
assert resp.context['cells'][0].pk == cell.pk
assert resp.context['cells'][0].repeat_index == 0
extra_ctx = re.findall(r'data-extra-context="(.*)"', resp.text)
cell_resp = app.get(cell_url + '?ctx=' + extra_ctx[0])
assert cell_resp.context['repeat_index'] == 0
assert 'Card Model 1' in cell_resp
assert '<p>Unknown Card</p>' in cell_resp
assert len(mock_send.call_args_list) == 1
assert '/api/cards/card_model_1/42/' in mock_send.call_args_list[0][0][0].url
assert 'Card Model 1' in result
assert '<p>Unknown Card</p>' in result
context['cards'] = Cards()
cell.card_id = '{% cards|objects:"card_model_1"|last|get:"id" %}' # syntax error
cell.card_ids = '42, , 35'
cell.save()
mock_send.reset_mock()
result = cell.render(context)
assert mock_send.call_args_list == []
assert result.replace('\n', '') == '' # empty-cell
resp = app.get(page.get_online_url())
assert len(resp.context['cells']) == 2
extra_ctx = re.findall(r'data-extra-context="(.*)"', resp.text)
for i in range(0, 2):
assert resp.context['cells'][i].pk == cell.pk
assert resp.context['cells'][i].repeat_index == i
cell_resp = app.get(cell_url + '?ctx=' + extra_ctx[i])
assert cell_resp.context['repeat_index'] == i
assert 'Card Model 1' in cell_resp
assert '<p>Unknown Card</p>' in cell_resp
assert len(mock_send.call_args_list) == 2
assert '/api/cards/card_model_1/42/' in mock_send.call_args_list[0][0][0].url
assert '/api/cards/card_model_1/35/' in mock_send.call_args_list[1][0][0].url
del context['card_not_found']
cell.card_id = '{{ cards|objects:"card_model_1"|last|get:"id" }}'
cell.card_ids = '{% cards|objects:"card_model_1"|last|get:"id" %}' # syntax error
cell.save()
mock_send.reset_mock()
result = cell.render(context)
resp = app.get(page.get_online_url())
assert len(resp.context['cells']) == 1
extra_ctx = re.findall(r'data-extra-context="(.*)"', resp.text)
cell_resp = app.get(cell_url + '?ctx=' + extra_ctx[0])
assert cell_resp.text.replace('\n', '') == '' # empty-cell
cell.card_ids = '{{ cards|objects:"card_model_1"|last|get:"id" }}'
cell.save()
mock_send.reset_mock()
resp = app.get(page.get_online_url())
assert len(resp.context['cells']) == 1
assert resp.context['cells'][0].pk == cell.pk
assert resp.context['cells'][0].repeat_index == 0
extra_ctx = re.findall(r'data-extra-context="(.*)"', resp.text)
cell_resp = app.get(cell_url + '?ctx=' + extra_ctx[0])
assert cell_resp.context['repeat_index'] == 0
assert len(mock_send.call_args_list) == 3
# page rendering
assert '/api/cards/card_model_1/list' in mock_send.call_args_list[0][0][0].url
assert '/api/cards/card_model_1/13/' in mock_send.call_args_list[1][0][0].url
assert 'Card Model 1' in result
assert '<p>Unknown Card</p>' in result
# cell rendering
assert '/api/cards/card_model_1/list' in mock_send.call_args_list[1][0][0].url
assert '/api/cards/card_model_1/13/' in mock_send.call_args_list[2][0][0].url
# with a card_id template, but result is empty
del context['card_model_1_id']
cell.card_id = '{{ foo }}'
for card_ids in [
'{% for card in cards|objects:"card_model_1" %}{{ card.id }},{% endfor %}',
'{{ cards|objects:"card_model_1"|getlist:"id"|join:"," }}',
]:
cell.card_ids = card_ids
cell.save()
mock_send.reset_mock()
resp = app.get(page.get_online_url())
assert len(resp.context['cells']) == 3
extra_ctx = re.findall(r'data-extra-context="(.*)"', resp.text)
for i in range(0, 3):
assert resp.context['cells'][i].pk == cell.pk
assert resp.context['cells'][i].repeat_index == i
cell_resp = app.get(cell_url + '?ctx=' + extra_ctx[i])
assert cell_resp.context['repeat_index'] == i
assert len(mock_send.call_args_list) == 7
# page rendering
assert '/api/cards/card_model_1/list' in mock_send.call_args_list[0][0][0].url
# cell rendering
for i in range(0, 3):
assert '/api/cards/card_model_1/list' in mock_send.call_args_list[i * 2 + 1][0][0].url
assert (
'/api/cards/card_model_1/%s/' % WCS_CARDS_DATA[i]['id']
in mock_send.call_args_list[i * 2 + 2][0][0].url
)
# with a card_ids template, but result is empty
cell.card_ids = '{{ foo }}'
cell.save()
assert cell.get_card_id(context) == ''
mock_send.reset_mock()
result = cell.render(context)
assert mock_send.call_args_list == []
assert result.replace('\n', '') == '' # empty-cell
resp = app.get(page.get_online_url())
assert len(resp.context['cells']) == 1
extra_ctx = re.findall(r'data-extra-context="(.*)"', resp.text)
cell_resp = app.get(cell_url + '?ctx=' + extra_ctx[0])
assert cell_resp.text.replace('\n', '') == '' # empty-cell
@mock.patch('combo.apps.wcs.utils.requests.send', side_effect=mocked_requests_send)
@ -2056,6 +2136,9 @@ def test_card_cell_render_user(mock_send, context, nocache):
cell.save()
context['card_model_1_id'] = 11
request = RequestFactory().get('/')
cell.modify_global_context(context, request)
cell.repeat_index = 0
context['synchronous'] = True # to get fresh content
assert context['request'].user is None
@ -2679,11 +2762,12 @@ def test_card_file_redirection(mock_send, app):
page.save()
cell = WcsCardInfosCell(page=page, placeholder='content', order=0)
cell.carddef_reference = 'default:card_model_1'
cell.card_id = '11'
cell.card_ids = '11'
cell.save()
resp = app.get('/one/')
ajax_cell_url = PyQuery(resp.text).find('[data-ajax-cell-url]').attr['data-ajax-cell-url']
resp = app.get(ajax_cell_url)
extra_ctx = re.findall(r'data-extra-context="(.*)"', resp.text)
resp = app.get(ajax_cell_url + '?ctx=' + extra_ctx[0])
file_url = PyQuery(resp.text).find('[download]').attr['href']
resp = app.get(file_url)
assert 'download?f=42' in resp.location