tutorial poner imagen fondo examples español python django pagination django-endless-pagination

python - poner - ¿Cómo hacer un postprocesamiento de resultados antes de renderizar con django interminable-paginación?



tutorial django (1)

Estoy tratando de averiguar si es posible ver el post-procesamiento en mi queryset antes de representarlo en una plantilla django que usa django-interminable-paginación para scroll infinito.

Tengo una lógica específica de la vista que omite ciertos resultados del conjunto de consultas en función del contexto, así como la adición de atributos a los objetos en la lista para que los utilicen las plantillas. Esta lógica no se puede ejecutar a través de SQL ya que no es inherente al modelo. Debe hacerse en python.

Con django-interminable-paginación y otros módulos de paginación django prelacionados, toda la lógica parece ser ejecutada por templatetags, impidiendo así la capacidad de hacer lógica de negocios antes de la etapa de renderización (que es un principio django).

Debido a que mi lógica de vista se ejecuta en el conjunto de resultados antes de que se ejecuten las etiquetas de la plantilla, estoy perdiendo las optimizaciones que ofrece este módulo (como las consultas SQL con paginación, por ejemplo, límite 20, desplazamiento 20). Mi código atraviesa toda la lista de resultados sin paginación cada vez que las páginas del usuario pasan por alto los beneficios de paginación diferida que ofrece la etiqueta de la plantilla.

A falta de mover mi código al módulo de paginación directamente (lo cual prefiero no hacer y requeriría agregar un montón de datos adicionales en el contexto de solicitud para usar en una etiqueta), ¿hay alguna alternativa?

¡Gracias!


Si mira la etiqueta lazy_paginate use la clase LazyPaginator para procesar el conjunto de preguntas. Puede anular esa clase para cumplir su propósito. Para hacer eso, necesitas escribir una etiqueta de plantilla personalizada . Más instrucciones en los comentarios del código.

* my_app / templatetags / custom_pagination_tags.py *

from django import template from endless_pagination.templatetags.endless import paginate from endless_pagination.paginators import LazyPaginator register = template.Library() Class CustomLazyPaginator(LazyPaginator): def page(self, number): page_obj = super(CustomLazyPaginator, self).page(number) # page function returns page object from that you could access object_list object_list = page_obj.object_list # Do some processing here for your queryset # Do not remove elements otherwise you will put your self in trouble # Just add some values in objects as you wanted to page_obj.object_list = object_list # override here return page_obj @register.tag def custom_lazy_paginate(parser, token): return paginate(parser, token, paginator_class=CustomLazyPaginator)

Ahora, en la plantilla, carga tus etiquetas de plantilla personalizadas y utiliza eso en su lugar:

{% load custom_pagination_tags %} {% custom_lazy_paginate queryset %}

Difícil: Primer acercamiento al contexto de solicitud de acceso en clase CustomLazyPaginator

Sí, hay una forma de pasar el contexto de la solicitud, pero para hacer eso debes anular la etiqueta de PaginateNode y también el método de render de PaginateNode como puedes ver aquí cuando llama al paginator_class y no pasa ninguna información de contexto. A continuación se detallan los pasos para lograr eso:

Agregue el método CustomLazyPaginator en CustomLazyPaginator :

def __init__(self, *args, **kwargs): self.context = kwargs.pop(''context'', None) super(CustomLazyPaginator, self).__init__(*args, **kwargs)

Copie la etiqueta de PaginateNode(paginator_class, objects, **kwargs) y cambie la declaración de PaginateNode(paginator_class, objects, **kwargs) de PaginateNode(paginator_class, objects, **kwargs) a CustomPaginateNode(paginator_class, objects, **kwargs) y escribiremos CustomPaginateNode continuación.

from endless_pagination.templatetags.endless import PAGINATE_EXPRESSION @register.tag def paginate(parser, token, paginator_class=None): # Validate arguments. try: tag_name, tag_args = token.contents.split(None, 1) except ValueError: msg = ''%r tag requires arguments'' % token.contents.split()[0] raise template.TemplateSyntaxError(msg) # Use a regexp to catch args. match = PAGINATE_EXPRESSION.match(tag_args) if match is None: msg = ''Invalid arguments for %r tag'' % tag_name raise template.TemplateSyntaxError(msg) # Retrieve objects. kwargs = match.groupdict() objects = kwargs.pop(''objects'') # The variable name must be present if a nested context variable is passed. if ''.'' in objects and kwargs[''var_name''] is None: msg = ( ''%(tag)r tag requires a variable name `as` argumnent if the '' ''queryset is provided as a nested context variable (%(objects)s). '' ''You must either pass a direct queryset (e.g. taking advantage '' ''of the `with` template tag) or provide a new variable name to '' ''store the resulting queryset (e.g. `%(tag)s %(objects)s as '' ''objects`).'' ) % {''tag'': tag_name, ''objects'': objects} raise template.TemplateSyntaxError(msg) # Call the node. return CustomPaginateNode(paginator_class, objects, **kwargs)

Elimine la siguiente importación que llamamos antes para evitar llamar a la función de paginate original:

from endless_pagination.templatetags.endless import paginate

Reemplaza el método de render de PaginateNode para pasar el contexto a nuestra clase CustomLazyPaginator :

from endless_pagination.templatetags.endless import PaginateNode from endless_pagination import ( settings, utils, ) class CustomPaginateNode(PaginateNode): def render(self, context): # Handle page number when it is not specified in querystring. if self.page_number_variable is None: default_number = self.page_number else: default_number = int(self.page_number_variable.resolve(context)) # Calculate the number of items to show on each page. if self.per_page_variable is None: per_page = self.per_page else: per_page = int(self.per_page_variable.resolve(context)) # Calculate the number of items to show in the first page. if self.first_page_variable is None: first_page = self.first_page or per_page else: first_page = int(self.first_page_variable.resolve(context)) # User can override the querystring key to use in the template. # The default value is defined in the settings file. if self.querystring_key_variable is None: querystring_key = self.querystring_key else: querystring_key = self.querystring_key_variable.resolve(context) # Retrieve the override path if used. if self.override_path_variable is None: override_path = self.override_path else: override_path = self.override_path_variable.resolve(context) # Retrieve the queryset and create the paginator object. objects = self.objects.resolve(context) paginator = self.paginator( objects, per_page, first_page=first_page, orphans=settings.ORPHANS, context=context) # <--- passing context here # Normalize the default page number if a negative one is provided. if default_number < 0: default_number = utils.normalize_page_number( default_number, paginator.page_range) # The current request is used to get the requested page number. page_number = utils.get_page_number_from_request( context[''request''], querystring_key, default=default_number) # Get the page. try: page = paginator.page(page_number) except EmptyPage: page = paginator.page(1) # Populate the context with required data. data = { ''default_number'': default_number, ''override_path'': override_path, ''page'': page, ''querystring_key'': querystring_key, } context.update({''endless'': data, self.var_name: page.object_list}) return ''''

Simple: segundo enfoque para el contexto de solicitud de acceso en CustomLazyPaginator Class

Simplemente instale django-contrib-requestprovider y agréguelo en middleware en django''s settings.py y acceda a la solicitud actual donde desee:

from gadjo.requestprovider.signals import get_request http_request = get_request()