Bug #41276
Une cellule "liste de liens" est vide quand elle est dans une cellule "Identitique à la page parent" (ParentContentCell)
0%
Description
Pour reproduire :
- sur une page, dans un placeholder, construire une cellule "Liste de liens" et y mettre 2 ou 3 liens
- sur une sous-page, poser une cellule "Identique à la page parent" dans le placeholder
dans la sous-page, la cellule "liste de liens" s'affiche mais avec une liste vide.
Fichiers
Révisions associées
Historique
Mis à jour par Thomas Noël il y a environ 4 ans
Je pense que c'est parce qu'on cherche les liens dans for cell in context.get('page_cells', []):
alors qu'on n'est plus sur la page de la cellule (celle où elle est instanciée).
Mis à jour par Thomas Noël il y a environ 4 ans
J'ai l'impression que c'est juste ça, ou bien je rate une subtilité ?
diff --git a/combo/data/models.py b/combo/data/models.py index a295707f..6f9581de 100644 --- a/combo/data/models.py +++ b/combo/data/models.py @@ -1241,11 +1241,7 @@ class LinkListCell(CellBase): def get_cell_extra_context(self, context): extra_context = super(LinkListCell, self).get_cell_extra_context(context) links = [] - for cell in context.get('page_cells', []): - if not hasattr(cell, 'add_as_link_label'): - continue - if not cell.placeholder == self.link_placeholder: - continue + for cell in self.get_items(): links.append(cell.get_cell_extra_context(context)) extra_context['links'] = links extra_context['more_links'] = []
Mis à jour par Frédéric Péters il y a environ 4 ans
J'ai l'impression que c'est juste ça, ou bien je rate une subtilité ?
Minimiser le nombre de requêtes.
Mis à jour par Thomas Noël il y a environ 4 ans
Frédéric Péters a écrit :
J'ai l'impression que c'est juste ça, ou bien je rate une subtilité ?
Minimiser le nombre de requêtes.
Yep.
Tenté sur http://git.entrouvert.org/combo.git/?h=wip%2F41276-linklist-in-parentcell
Et oui ça requête plus et donc le test « assert len(ctx.captured_queries) == 31 » n'est pas content.
Ceci étant c'est a priori le seul pépin.
Si quelqu'un a une autre idée...
Mis à jour par Frédéric Péters il y a environ 4 ans
Et là le test c'est sur la page du manager, donc moins important que le front côté nombre de requêtes. (mais modif sans effet vu que pas de problème côté manager).
Ce qu'il faut (d'un rapide regard) c'est adapter le get_parent_cells(), modifier
CellBase.get_cells(placeholder=self.placeholder, page__in=pages)
pour qu'il récupère aussi les cellules faisant partie de "liste de liens". (et une approximation genre placeholder__startswith='_' doit être ok, je pense).
Mis à jour par Frédéric Péters il y a environ 4 ans
- Fichier 0001-misc-get-cells-from-private-placeholders-in-parent-a.patch 0001-misc-get-cells-from-private-placeholders-in-parent-a.patch ajouté
- Statut changé de Nouveau à Solution proposée
- Patch proposed changé de Non à Oui
Voilà, avec un moche mais efficace,
+ parent_cells = [seen.setdefault((x.__class__, x.id), True) and x + for x in parent_cells if (x.__class__, x.id) not in seen]
Mis à jour par Thomas Noël il y a environ 4 ans
A priori le seen ajouté dans combo/data/models.py ne sert à rien (sans doute un reste d'idée ?)
Frédéric Péters a écrit :
Si j'ai compris il s'agit de ne pas avoir de doublons. On (Lauréline et moi) a deux questions :Voilà, avec un moche mais efficace,
- c'est pour garder l'ordre que tu n'utilise pas un set ? Ou bien pour une question d'efficacité ?
- et aussi, pourquoi enlever les doublons ?
Mis à jour par Lauréline Guérin il y a environ 4 ans
(et aussi le remplissage du seen
dans la méthode get_parents_cells
qui semble ne pas servir à grand chose :) )
Mis à jour par Frédéric Péters il y a environ 4 ans
A priori le seen ajouté dans combo/data/models.py ne sert à rien (sans doute un reste d'idée ?)
Yes, c'était dans l'idée de faire ça à cet endroit, mais ça ne marche pas.
Si j'ai compris il s'agit de ne pas avoir de doublons. On (Lauréline et moi) a deux questions :
c'est pour garder l'ordre que tu n'utilise pas un set ? Ou bien pour une question d'efficacité ?
Pour le seen ? C'est par habitude et certitude concernant les performances.
et aussi, pourquoi enlever les doublons ?
Quand on a une ParentContentCell, extend_with_parent_cells() est appelé pour étendre la liste des cellules figurant sur la page; l'appel faisait placeholder=self.placeholder et donc à étendre la zone "pied de page" on trouvait uniquement les cellules du pied de page, très bien.
À chercher également les cellules avec un placeholder commençant par un _, on attrape les "sous-cellules" (lien d'une cellule liste de liens, en l'occurence).
Les doublons arrivent s'il y a une seconde ParentContentCell; elle va aussi faire le même job, récupérer les mêmes "sous-cellules", et celles-ci vont se trouver deux fois dans la liste des cellules figurant dans la page.
Ensuite, la cellule LinkListCell va faire
links = [] for cell in context.get('page_cells', []):
et si dans page_cells on avait laissé les cellules en double, elles seraient ici reprises deux fois.
Mis à jour par Thomas Noël il y a environ 4 ans
- Statut changé de Solution proposée à Solution validée
Frédéric Péters a écrit :
Les doublons arrivent s'il y a une seconde ParentContentCell
J'ai tout pigé ; go.
Mis à jour par Frédéric Péters il y a environ 4 ans
- Fichier 0001-misc-get-cells-from-private-placeholders-in-parent-a.patch 0001-misc-get-cells-from-private-placeholders-in-parent-a.patch ajouté
- Statut changé de Solution validée à Solution proposée
Je modifie un peu, pour filtrer sur des préfixes spécifiques, mon idée étant que sur une page comme "mon tableau de bord" le filtre _startswith='' attraperait toutes les cellules des tableaux de bord de tous les usagers.
diff --git a/combo/data/models.py b/combo/data/models.py index 35d5bb23..d5cd4219 100644 --- a/combo/data/models.py +++ b/combo/data/models.py @@ -569,6 +569,7 @@ class CellBase(six.with_metaclass(CellMeta, models.Model)): default_form_class = None manager_form_factory_kwargs = {} manager_form_template = 'combo/cell_form.html' + children_placeholder_prefix = None visible = True user_dependant = False @@ -1213,6 +1214,7 @@ class LinkListCell(CellBase): template_name = 'combo/link-list-cell.html' manager_form_template = 'combo/manager/link-list-cell-form.html' + children_placeholder_prefix = '_linkslist:' invalid_reason_codes = { 'data_link_invalid': _('Invalid link'), @@ -1223,7 +1225,7 @@ class LinkListCell(CellBase): @property def link_placeholder(self): - return '_linkslist:{}'.format(self.pk) + return self.children_placeholder_prefix + str(self.pk) def get_items(self, prefetch_validity_info=False): return CellBase.get_cells( @@ -1386,7 +1388,10 @@ class ParentContentCell(CellBase): cells_by_page[page.id] = [] # get cells from placeholder + cells in private placeholders that may # be used by actual cells. - for cell in CellBase.get_cells(page__in=pages, extra_filter=Q(placeholder=self.placeholder) | Q(placeholder__startswith='_')): + placeholder_filter = Q(placeholder=self.placeholder) + for klass in CellBase.get_cell_classes(lambda x: bool(x.children_placeholder_prefix)): + placeholder_filter |= Q(placeholder__startswith=klass.children_placeholder_prefix) + for cell in CellBase.get_cells(page__in=pages, extra_filter=placeholder_filter): cells_by_page[cell.page_id].append(cell) cells = cells_by_page[pages[-1].id]
Mis à jour par Thomas Noël il y a environ 4 ans
- Statut changé de Solution proposée à Solution validée
Je préférerais que children_placeholder_prefix ne contienne ni le "_" ni le ":"
children_placeholder_prefix = 'linklist' ... @property def link_placeholder(self): if children_placeholder_prefix: return '_{}:{}'.format(self.children_placeholder_prefix, self.pk)
et donc plus bas :
for klass in CellBase.get_cell_classes(lambda x: bool(x.children_placeholder_prefix)): placeholder_filter |= Q(placeholder__startswith='_' + klass.children_placeholder_prefix + ':')
et en écrivant ça je me dis que c'est pas joli. Laissons le children_placeholder_prefix = '_linklist:'
mais pensons à respecter ce format pour les prochaines fois.
Sur ce CellBase.get_cell_classes(lambda x: bool(x.children_placeholder_prefix))
je trouverai plus "lisible" d'écrire CellBase.get_cell_classes(class_filter=lambda x: ...)
même si on ne le fait nulle part ailleurs.
Bref, allez, c'est un ack, fait.
Mis à jour par Frédéric Péters il y a environ 4 ans
- Statut changé de Solution validée à Résolu (à déployer)
Poussé tel quel,
commit d66e3b55622bf48222561390668a08b5ebeab1b9 Author: Frédéric Péters <fpeters@entrouvert.com> Date: Fri Apr 3 14:43:58 2020 +0200 misc: get cells from private placeholders in parent acquisition (#41276)
Mis à jour par Frédéric Péters il y a environ 4 ans
- Statut changé de Résolu (à déployer) à Solution déployée
misc: get cells from private placeholders in parent acquisition (#41276)