Tengo un problema con .exclude() al hacer un QuerySet.
Mis modelos involucrados son:
Profesión
class Profession(models.Model): profession_name = models.CharField(max_length=20) equipment = models.ManyToManyField(Equipment, blank=True) ability = models.ManyToManyField(Ability, blank=True) skill = models.ManyToManyField(Skill, blank=True) skill_advanced = models.ManyToManyField(SkillAdvanced, blank=True)Habilidad
class Ability(models.Model): ability_name = models.CharField(max_length=35)Cuando creo QuerySet con:
self.prof_abilities = Profession.objects.filter(profession_name="Acolyte").values('ability')Yo obtengo:
<QuerySet [{'ability': 2}, {'ability': 69}, {'ability': 81}, {'ability': 86}, {'ability': 23}]>Pero me gustaría excluir algunos valores, así que uso esto en su lugar:
self.prof_abilities = Profession.objects.filter(profession_name="Acolyte").exclude(ability__in=[2, 23, 81, 86]).values('ability') Pero el resultado es un QuerySet vacío: <QuerySet []> .
Probé varios ajustes como .exclude(ability__id__in=[2, 23, 81, 86]) o .exclude(ability__ability_name__in=['Foo name', 'Bar name'] pero sin éxito.
Soy nuevo en Django, así que si esto es algo obvio, también agradecería algunos consejos sobre dónde leer más sobre mi error.
Su conjunto de consultas es para el modelo Profession , por lo tanto, cuando escribe queryset.exclude(ability__in=<list_of_abilities>) obtiene un conjunto de consultas donde excluye las instancias Profession (No Ability ) donde la habilidad está en la lista dada, es decir, si alguna de las Ability relacionado con una Profession está en esa lista, esa profesión sería excluida. En cambio, si primero obtiene el objeto Profession y luego filtra en el administrador de relaciones, obtendrá el resultado esperado:
queryset = Profession.objects.filter(profession_name="Acolyte") for profession in queryset: print(profession.ability.exclude(id__in=[2, 23, 81, 86]))Como Ability es manyToManyField , cada objeto profession.ability tendrá django.db.models.fields.related.ManyRelatedManager y no la lista directa de objetos de habilidad. Entonces, si desea obtener Todas las profesiones que excluyen la capacidad con identificaciones específicas, puede intentar cambiar su consulta de
self.prof_abilities = Profession.objects.filter(profession_name="Acolyte").exclude(ability__in=[2, 23, 81, 86]).values('ability')para
self.prof_abilities = Profession.objects.filter(profession_name="Acolyte").exclude(ability__in=Ability.objects.filter(id__in=[2, 23, 81, 86])).values('ability') filter y exclude se comporta de manera diferente con respecto a multi-valued relationships .
Aunque no encontré un enlace para una explicación válida de mi respuesta, aquí hay un enlace de la documentación que discute algo relacionado
Desplácese hacia abajo para note parte del enlace de esta sección: https://docs.djangoproject.com/en/3.2/topics/db/queries/#spanning-multi-valued-relationships