Django filtro de muchos a muchos con contiene


Estoy tratando de filtrar un montón de objetos a través de una relación de muchos a muchos. Debido a que el campo trigger_roles puede contener varias entradas, probé con el filtro contains. Pero como está diseñado para ser utilizado con cadenas, estoy bastante indefenso sobre cómo debo filtrar esta relación (puedes ignorar el atm values_list ().).

Esta función se adjunta al perfil de usuario:

def getVisiblePackages(self):
    visiblePackages = {}   
    for product in self.products.all():
        moduleDict = {}
        for module in product.module_set.all():
            pkgList = []
            involvedStatus = module.workflow_set.filter(trigger_roles__contains=self.role.id,allowed=True).values_list('current_state', flat=True)

Mi modelo de flujo de trabajo se ve así (simplificado):

class Workflow(models.Model):
    module = models.ForeignKey(Module)
    current_state = models.ForeignKey(Status)
    next_state = models.ForeignKey(Status)
    allowed = models.BooleanField(default=False)
    involved_roles = models.ManyToManyField(Role, blank=True, null=True)
    trigger_roles = models.ManyToManyField(Role, blank=True, null=True)

Aunque la solución podría ser silenciosa simple, mi cerebro no me lo dirá.

Gracias por su ayuda.

Author: Grave_Jumper, 2010-12-22

4 answers

¿has probado algo como esto:

module.workflow_set.filter(trigger_roles__in=[self.role], allowed=True)

O simplemente si self.role.id no es una lista de pks:

module.workflow_set.filter(trigger_roles__id__exact=self.role.id, allowed=True)
 77
Author: mouad,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2015-08-03 03:25:01

El enfoque más simple para lograr esto sería verificar la equalty sobre toda la instancia (en lugar del id) en el ManyToManyField. Eso se ve si la instancia está dentro de la relación de muchos a muchos. Ejemplo:

module.workflow_set.filter(trigger_roles=self.role, allowed=True)
 10
Author: Caumons,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2013-08-19 15:16:53

La singularidad es casi correcta con el primer ejemplo. Sólo tienes que asegurarte de que es una lista. El segundo ejemplo, comprobar el trigger_roles__id__exact es una mejor solución.

module.workflow_set.filter(trigger_roles__in=[self.role.id],allowed=True)
 4
Author: Josh Smeaton,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2010-12-22 13:38:33

Sé que esta es una vieja pregunta, pero parece que el OP nunca obtuvo la respuesta que estaba buscando. Si tienes dos conjuntos de muchos campos que quieres comparar, el truco es usar el operador __in, no contains. Así, por ejemplo, si tienes un modelo "Event" con una ManyToMany a "Group" en el campo eventgroups, y tu modelo de Usuario (obviamente) se adjunta a Group, puedes consultar de la siguiente manera:

Event.objects.filter(eventgroups__in=u.groups.all())

 3
Author: shacker,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2016-06-01 00:28:41