Eu tenho um modelo:
class Zone(models.Model):
name = models.CharField(max_length=128)
users = models.ManyToManyField(User, related_name='zones', null=True, blank=True)
E preciso criar um filtro ao longo das linhas de:
u = User.objects.filter(...zones contains a particular zone...)
Ele deve ser um filtro no usuário e um único parâmetro de filtro. A razão para isso é que estou construindo uma string de consulta de URL para filtrar a lista de alterações do usuário administrador:http://myserver/admin/auth/user/?zones=3
Parece que deveria ser simples, mas meu cérebro não está cooperando!
django
django-models
Andy Baker
fonte
fonte
User.objects.filter(zones__id=<id>)
ouUser.objects.filter(zones__in=<id(s)>)
bom para isso?User.objects.filter(zones__in=<id(s)>)
provavelmente deveria serUser.objects.filter(zones__id__in=<id(s)>)
Respostas:
Apenas reafirmando o que Tomasz disse.
Existem muitos exemplos de
FOO__in=...
filtros de estilo nos testes muitos para muitos e muitos para um . Aqui está a sintaxe para seu problema específico:A sintaxe de sublinhado duplo (__) é usada em todo o lugar ao trabalhar com conjuntos de consultas .
fonte
...__in
exemplos depois# filtering on a few zones, by id
. Aqueles mostram a filtragem de vários IDs / objetos (neste caso). Basta passar os IDs / objetos zone1, zone3 e zone10 com os quais você se preocupa. Ou adicione um quarto, se necessário.Observe que, se o usuário estiver em várias zonas usadas na consulta, provavelmente você deseja adicionar .distinct (). Caso contrário, você obterá um usuário várias vezes:
fonte
Outra maneira de fazer isso é percorrer a tabela intermediária. Eu expressaria isso dentro do Django ORM assim:
seria bom se não precisasse do
.values('user')
especificado, mas o Django (versão 3.0.7) parece precisar.o código acima acabará gerando SQL parecido com:
o que é legal porque não possui junções intermediárias que podem causar o retorno de usuários duplicados
fonte