Cómo editar la lista de filtros de un queryset

Esta característica se utiliza en una vista donde se enumeran los resultados de búsqueda. En mi formulario de búsqueda, tengo algunos ModelChoiceFields para buscar por claves externas. El flujo de trabajo habitual significa que nuestra búsqueda actual sea cada vez más precisa, por lo que para inhabilitar muchos resultados no pertinentes, estoy intentando eliminar entradas que no devolverían ningún resultado si no cambia ningún otro parámetro de búsqueda.

Estoy usando un objeto queryset para restringir las proposiciones en algunas listas desplegables. Utilizo estas listas desplegables para filtrar por claves externas mi lista de objetos.

Mi argumento de función para filtrar es un conjunto de consultas de Objetos, por ahora:

class MySearchForm(Form): things = ModelChoiceField(queryset=models.Thing.objects.none()) def __init__(self, *args, **kwargs): my_objects_queryset = kwargs.pop('my_objects_queryset',models.Thing.objects.all()) super(MySearchForm, self).__init__(*args, **kwargs) self.fields['things'].queryset = \ models.Thing.objects.filter(object__in=my_objects_queryset).distinct() 

Mi problema es cómo eliminar un ‘donde cerca’ de un query_set existente. Aquí, quiero eliminar de my_objects_queryset donde cierra qué filtro por thing = ForeignKey(models.Thing)

¿Es posible?

Algo así como una forma de enumerar todos los filtros de nuestro queryset y editarlos / eliminarlos sobre la marcha.

Respuesta corta:

No, no puedes hacer eso.

Respuesta larga:

Teóricamente, puede ser posible (hasta cierto punto de todos modos) pero ciertamente no es aconsejable .

(No he estudiado completamente la fuente de django, así que lo que sigue es el resultado de un simple ascenso en el árbol de llamadas).

Al observar el origen de QuerySet , filter() y exclude() devuelve un clon del queryset con la nueva regla agregada (usando clone.query.add_q() ).

clone.query es un objeto que representa una consulta SQL, mientras que el método add_q () agrega la nueva regla a clone.query.where que es esencialmente un nodo raíz de un árbol .

La forma en que se agrega el nuevo nodo al árbol depende de si la regla se debe conectar con una cláusula AND o OR . Esto es importante ya que afecta la corrección de la consulta SQL final que se genera .

Por lo tanto, para enumerar los filtros asignados a un queryset, uno “simplemente” necesita entender cómo se representa el árbol queryset.query.where (vea django.utils.tree ).

El bit difícil es, por supuesto, la eliminación de los filtros de modo que no afecte a las reglas restantes. Me abstendré de ofrecer una solución ya que no hay garantía de que la implementación no cambie, lo que invalida la solución. Sospecho que es posible hacerlo, pero huele a algo que solo debe hacerse por interés académico, o en absoluto.

Algunos hacking aquí.

Puede omitirlo “restableciendo” los filtros actuales de la siguiente manera:

 from django.db.models.sql.where import WhereNode qs = YourModel.objects.filter(column=1).all() qs.query.where = WhereNode() # resets current filters qs.all() # now you can apply new filters