Tengo una mesa de trabajo generada por django-tables2:
my_filter = TestFilter(request.POST) table = TestTable(TestObj.objects.all(), order_by="-my_date") RequestConfig(request, paginate={"per_page": 10}).configure(table) return render(request, 'test_app/index.html', {'table': table, 'my_filter': my_filter})
El código anterior devuelve una tabla con cientos de objetos que están cuidadosamente paginados con 10 elementos por página. Cuando hago clic en “Siguiente” en la parte inferior de la tabla, la paginación funciona bien y puedo navegar a través de diferentes páginas. Sin embargo, noté el siguiente comportamiento:
my_filter
que muestra un subconjunto de la tabla original sin filtrar my_filter
nuevamente para ver la segunda página de la tabla filtrada. Me gustaría que el filtro persista mientras navega por diferentes páginas. Encontré una pregunta similar aquí . Esa solución indica que el código html necesita ser alterado. Sin embargo, en mi caso, django-tables2 está generando el html.
¿Cómo puedo implementar correctamente la paginación con filtrado utilizando django-tables2?
-Actualizar-
He intentado usar GET en lugar de POST:
if request.method == 'GET': my_filter = TestFilter(request.GET) my_choice = my_filter.data['my_choice'] table = TestTable(TestObj.objects.filter(choice=my_choice), order_by="-my_date") RequestConfig(request, paginate={"per_page": 10}).configure(table) return render(request, 'test_app/index.html', {'table': table, 'my_filter': my_filter})
Mi plantilla:
{% csrf_token %} {{ my_filter }}
Esto da como resultado que KeyError se deba a que my_choice
no existe en GET. Como resultado, la página ni siquiera se carga.
¿Qué versión de django_tables2 estás usando? Verifiqué la fuente y vi que django_tables2 está usando una etiqueta de plantilla llamada querystring
de querystring
para crear los enlaces de paginación en la plantilla table.html
. la etiqueta de la querystring
actualiza la url actual con los parámetros de paginación. así que django_tables2 soporta paginación + filtrado fuera de la caja (eso es lo que recordé).
Intente actualizar a la última versión de django_tables2 y asegúrese de estar usando la plantilla table.html
predeterminada para representar sus tablas.
¿También está enviando su formulario de filtro con GET o POST? Por favor, asegúrese de que lo envíe con GET!
Finalmente, por favor, eche un vistazo a mi respuesta a esta pregunta Tablas de Django – Filtrado de columnas
actualización: eché un vistazo más de cerca al código que publicaste: en primer lugar, estás pasando los datos de la publicación al filtro: no puedes usar la POST para eso, la POST solo se debe usar para acciones que modifican tus datos. También vi que no filtres nada, ¡sino que pasas .all () a la tabla! ¿Dónde se realiza el filtrado real? ¡Debes pasar los datos filtrados a la tabla como describo en la respuesta anterior!
actualización 2: el problema con su vista es que cuando visita la página por primera vez, el diccionario GET
no contiene el atributo my_choice
por lo que generará una excepción cuando intente acceder al atributo my_choice
través del operador []
, por lo que debería verificar Si realmente existe usando, por ejemplo, .get()
, algo como esto:
my_filter = TestFilter(request.GET) my_choice = my_filter.data.get('my_choice') # This won't throw an exception if my_choice: # If my_choice existed on the GET dictionary this will return non-null value table = TestTable(TestObj.objects.filter(choice=my_choice), order_by="-my_date") else: table = TestTable(TestObj.objects.all(), order_by="-my_date") RequestConfig(request, paginate={"per_page": 10}).configure(table) return render(request, 'test_app/index.html', {'table': table, 'my_filter': my_filter})
Lo anterior debería funcionar, sin embargo, al hacer el filtrado de consultas usted mismo, está violando casi todas las filosofías de diseño de django .
Por eso le dije que leyera mi otra respuesta a la pregunta similar ( Tablas de Django – Filtrado de columnas ) en la que recomiendo usar django-filter, que es un paquete que se usa explícitamente para filtrar conjuntos de consultas. Verifique la documentación o mi respuesta para ver cómo se puede usar (Me encantaría ayudarlo si tiene alguna pregunta).
Además, hay una serie de otros problemas menores con su código:
No es necesario que compruebe si el request.method
es GET
; siempre será GET
ya que no hará ningún POST
s
No debe incluir {{ csrf_token }}
a su plantilla, solo se necesita para POST
.
La clase TestFilter
es en realidad un Form
, por eso recomiendo nombrarlo TestFilterForm
o algo similar: si usó django-filter, crearía una clase FilterSet que se llamaría TestFilter
. El nombre correcto de las clases es muy importante, cuando vi su código por primera vez, ¡pensé que la clase TestFilter
era un FilterSet
y no un Form
!