data: mark json config cell as invalid if not found in settings (#71168) #5
|
@ -26,6 +26,9 @@ class DataConfig(AppConfig):
|
||||||
from combo.data.models import CellBase
|
from combo.data.models import CellBase
|
||||||
|
|
||||||
cell_classes = [c for c in self.get_models() if c in get_cell_classes()]
|
cell_classes = [c for c in self.get_models() if c in get_cell_classes()]
|
||||||
for cell in CellBase.get_cells(cell_filter=lambda x: x in cell_classes, page__snapshot__isnull=True):
|
|
||||||
|
for cell in CellBase.get_cells(
|
||||||
|
cell_filter=lambda x: x in cell_classes, page__snapshot__isnull=True, get_all_objects=True
|
||||||
|
):
|
||||||
if hasattr(cell, 'check_validity'):
|
if hasattr(cell, 'check_validity'):
|
||||||
cell.check_validity()
|
cell.check_validity()
|
||||||
|
|
|
@ -1040,6 +1040,7 @@ class CellBase(models.Model, metaclass=CellMeta):
|
||||||
select_related=None,
|
select_related=None,
|
||||||
load_contenttypes=False,
|
load_contenttypes=False,
|
||||||
cells_exclude=None,
|
cells_exclude=None,
|
||||||
|
get_all_objects=False,
|
||||||
**kwargs,
|
**kwargs,
|
||||||
):
|
):
|
||||||
"""Returns the list of cells of various classes matching **kwargs"""
|
"""Returns the list of cells of various classes matching **kwargs"""
|
||||||
|
@ -1074,7 +1075,10 @@ class CellBase(models.Model, metaclass=CellMeta):
|
||||||
continue
|
continue
|
||||||
if cell_filter and not cell_filter(klass):
|
if cell_filter and not cell_filter(klass):
|
||||||
continue
|
continue
|
||||||
cells_queryset = klass.objects.filter(**kwargs)
|
manager = klass.objects
|
||||||
|
if get_all_objects and hasattr(klass, 'all_objects'):
|
||||||
|
manager = klass.all_objects
|
||||||
|
cells_queryset = manager.filter(**kwargs)
|
||||||
if cells_exclude:
|
if cells_exclude:
|
||||||
cells_queryset = cells_queryset.exclude(cells_exclude)
|
cells_queryset = cells_queryset.exclude(cells_exclude)
|
||||||
if extra_filter:
|
if extra_filter:
|
||||||
|
@ -2360,10 +2364,15 @@ class ConfigJsonCellManager(models.Manager):
|
||||||
@register_cell_class
|
@register_cell_class
|
||||||
class ConfigJsonCell(JsonCellBase):
|
class ConfigJsonCell(JsonCellBase):
|
||||||
objects = ConfigJsonCellManager()
|
objects = ConfigJsonCellManager()
|
||||||
|
|||||||
|
all_objects = models.Manager()
|
||||||
|
|
||||||
key = models.CharField(max_length=50)
|
key = models.CharField(max_length=50)
|
||||||
parameters = JSONField(blank=True, default=dict)
|
parameters = JSONField(blank=True, default=dict)
|
||||||
|
|
||||||
|
invalid_reason_codes = {
|
||||||
|
'settings_not_found': _('Cell not found in settings'),
|
||||||
|
}
|
||||||
|
|
||||||
def __str__(self):
|
def __str__(self):
|
||||||
return force_str(_('%s (JSON Cell)') % self.get_label())
|
return force_str(_('%s (JSON Cell)') % self.get_label())
|
||||||
|
|
||||||
|
@ -2383,6 +2392,8 @@ class ConfigJsonCell(JsonCellBase):
|
||||||
return l
|
return l
|
||||||
|
|
||||||
def get_label(self):
|
def get_label(self):
|
||||||
|
if self.key not in settings.JSON_CELL_TYPES:
|
||||||
|
return _('Unknown ConfigJsonCell %s') % self.key
|
||||||
return settings.JSON_CELL_TYPES[self.key]['name']
|
return settings.JSON_CELL_TYPES[self.key]['name']
|
||||||
|
|
||||||
def set_variant(self, variant):
|
def set_variant(self, variant):
|
||||||
|
@ -2465,6 +2476,18 @@ class ConfigJsonCell(JsonCellBase):
|
||||||
self.template_string = self.parameters['template_string']
|
self.template_string = self.parameters['template_string']
|
||||||
return super().render(context)
|
return super().render(context)
|
||||||
|
|
||||||
|
def check_validity(self):
|
||||||
|
if self.key not in settings.JSON_CELL_TYPES:
|
||||||
|
self.mark_as_invalid('settings_not_found')
|
||||||
|
return
|
||||||
|
validity_info = self.get_validity_info()
|
||||||
|
if validity_info is None:
|
||||||
|
return
|
||||||
|
if validity_info.invalid_reason_code != 'settings_not_found':
|
||||||
|
# don't overwrite other invalid reasons
|
||||||
|
return
|
||||||
|
self.mark_as_valid()
|
||||||
|
|
||||||
|
|
||||||
@receiver(pre_save, sender=Page)
|
@receiver(pre_save, sender=Page)
|
||||||
def create_redirects(sender, instance, raw, **kwargs):
|
def create_redirects(sender, instance, raw, **kwargs):
|
||||||
|
|
|
@ -185,7 +185,10 @@ site_import = SiteImportView.as_view()
|
||||||
|
|
||||||
def invalid_cell_report(request):
|
def invalid_cell_report(request):
|
||||||
invalid_cells = CellBase.get_cells(
|
invalid_cells = CellBase.get_cells(
|
||||||
page__snapshot__isnull=True, validity_info__invalid_since__isnull=False, load_contenttypes=True
|
page__snapshot__isnull=True,
|
||||||
|
validity_info__invalid_since__isnull=False,
|
||||||
|
load_contenttypes=True,
|
||||||
|
get_all_objects=True,
|
||||||
)
|
)
|
||||||
# manual prefetch of cell pages (for ordering and placeholders)
|
# manual prefetch of cell pages (for ordering and placeholders)
|
||||||
all_pages_by_pk = {p.pk: p for p in Page.objects.filter(snapshot__isnull=True)}
|
all_pages_by_pk = {p.pk: p for p in Page.objects.filter(snapshot__isnull=True)}
|
||||||
|
|
|
@ -1258,6 +1258,44 @@ def test_config_json_cell_validity(settings, context):
|
||||||
assert ValidityInfo.objects.exists() is False
|
assert ValidityInfo.objects.exists() is False
|
||||||
|
|
||||||
|
|
||||||
|
def test_config_json_cell_check_validity(settings):
|
||||||
|
settings.JSON_CELL_TYPES = {
|
||||||
|
'test-config-json-cell': {
|
||||||
|
'name': 'Foobar',
|
||||||
|
},
|
||||||
|
}
|
||||||
|
page = Page.objects.create(title='example page', slug='example-page')
|
||||||
|
cell = ConfigJsonCell.objects.create(
|
||||||
|
page=page,
|
||||||
|
placeholder='content',
|
||||||
|
order=1,
|
||||||
|
key='test-config-json-cell',
|
||||||
|
)
|
||||||
|
cell.check_validity()
|
||||||
|
assert ValidityInfo.objects.exists() is False
|
||||||
|
|
||||||
|
settings.JSON_CELL_TYPES = {}
|
||||||
|
cell.check_validity()
|
||||||
|
validity_info = ValidityInfo.objects.latest('pk')
|
||||||
|
assert validity_info.invalid_reason_code == 'settings_not_found'
|
||||||
|
assert validity_info.invalid_since is not None
|
||||||
|
|
||||||
|
settings.JSON_CELL_TYPES = {
|
||||||
|
'test-config-json-cell': {
|
||||||
|
'name': 'Foobar',
|
||||||
|
},
|
||||||
|
}
|
||||||
|
validity_info.invalid_reason_code = 'foobar'
|
||||||
|
validity_info.save()
|
||||||
|
cell.check_validity()
|
||||||
|
assert ValidityInfo.objects.exists() is True
|
||||||
|
|
||||||
|
validity_info.invalid_reason_code = 'settings_not_found'
|
||||||
|
validity_info.save()
|
||||||
|
cell.check_validity()
|
||||||
|
assert ValidityInfo.objects.exists() is False
|
||||||
|
|
||||||
|
|
||||||
def test_json_force_async():
|
def test_json_force_async():
|
||||||
cell = JsonCell()
|
cell = JsonCell()
|
||||||
cell.url = 'http://example.net/test-force-async'
|
cell.url = 'http://example.net/test-force-async'
|
||||||
|
@ -1623,7 +1661,7 @@ def test_hourly():
|
||||||
for klass in cell_classes:
|
for klass in cell_classes:
|
||||||
klass.objects.create(page=page, placeholder='content', order=0)
|
klass.objects.create(page=page, placeholder='content', order=0)
|
||||||
for klass in cell_classes:
|
for klass in cell_classes:
|
||||||
if klass in [LinkCell, LinkListCell]:
|
if klass in [LinkCell, LinkListCell, ConfigJsonCell]:
|
||||||
with mock.patch('combo.data.models.%s.check_validity' % klass.__name__) as check_validity:
|
with mock.patch('combo.data.models.%s.check_validity' % klass.__name__) as check_validity:
|
||||||
appconfig.hourly()
|
appconfig.hourly()
|
||||||
assert check_validity.call_args_list == [mock.call()]
|
assert check_validity.call_args_list == [mock.call()]
|
||||||
|
|
|
@ -1272,6 +1272,17 @@ def test_invalid_cell_report(app, admin_user):
|
||||||
resp = app.get('/manage/cells/invalid-report/')
|
resp = app.get('/manage/cells/invalid-report/')
|
||||||
assert resp.context['object_list'] == [cell]
|
assert resp.context['object_list'] == [cell]
|
||||||
|
|
||||||
|
# unknown config cell
|
||||||
|
cell2 = ConfigJsonCell.objects.create(
|
||||||
|
page=page,
|
||||||
|
placeholder='content',
|
||||||
|
order=1,
|
||||||
|
key='test-config-json-cell',
|
||||||
|
)
|
||||||
|
cell2.mark_as_invalid('settings_not_found')
|
||||||
|
resp = app.get('/manage/cells/invalid-report/')
|
||||||
|
assert resp.context['object_list'] == [cell, cell2]
|
||||||
|
|
||||||
|
|
||||||
def test_duplicate_page(app, admin_user):
|
def test_duplicate_page(app, admin_user):
|
||||||
page = Page.objects.create(
|
page = Page.objects.create(
|
||||||
|
|
Loading…
Reference in New Issue
Ce manager fait un
queryset.filter(key__in=settings.JSON_CELL_TYPES.keys())
=> nécessité d'avoir un autre manager qui ne filtre pas sur les settings, pour le job cron, et pour la page de rapport des anomalies.