django filter list tag__in с & ldquo; & & rdquo; оператор [дубликат]

Одним словом, нет.

Цитата из Wikipedia :

Разыменование указателя NULL обычно приводит к попытке чтения или записи из памяти, которая не отображается - вызывает ошибку сегментации или нарушение доступа. Это может представлять собой проявителя в виде сбоя программы или быть преобразовано в исключение, которое может быть обнаружено. Однако есть определенные обстоятельства, когда это не так. Например, в режиме реального времени x86 адрес 0000: 0000 является читаемым и обычно записывается на запись, поэтому разыменование нулевого указателя является абсолютно корректным, но обычно нежелательным действием, которое может привести к неопределенному, но не аварийному поведению в приложении. Также обратите внимание, что бывают случаи, когда разыменование NULL является преднамеренным и четко определенным; например, код BIOS, написанный на C для 16-разрядных устройств реального времени x86, может записывать IDT на физическом адресе 0 машины путем разыменования указателя NULL для записи. Компилятор также может оптимизировать разыменование указателя NULL, избегая ошибки сегментации, но вызывая другое нежелательное поведение ...

В C поведение разыменования нулевого указателя есть undefined .

blockquote>

Также проверьте этот wild example указателя нулевого класса разыменованный, но который все еще работает просто отлично.

В принципе, не делайте этого, но тогда вы знали, что:)

75
задан Sander van Leeuwen 23 February 2012 в 15:25
поделиться

4 ответа

Резюме:

. Один из вариантов, как было предложено jpic и sgallen в комментариях, добавить .filter() для каждой категории. Каждый дополнительный filter добавляет больше объединений, что не должно быть проблемой для небольшого набора категорий.

Существует агрегация подход . Этот запрос будет короче и, возможно, быстрее для большого набора категорий.

У вас также есть возможность использовать пользовательские запросы .


Some Примеры

Настройка теста:

class Photo(models.Model):
    tags = models.ManyToManyField('Tag')

class Tag(models.Model):
    name = models.CharField(max_length=50)

    def __unicode__(self):
        return self.name

In [2]: t1 = Tag.objects.create(name='holiday')
In [3]: t2 = Tag.objects.create(name='summer')
In [4]: p = Photo.objects.create()
In [5]: p.tags.add(t1)
In [6]: p.tags.add(t2)
In [7]: p.tags.all()
Out[7]: [<Tag: holiday>, <Tag: summer>]

Использование прикованных фильтров :

In [8]: Photo.objects.filter(tags=t1).filter(tags=t2)
Out[8]: [<Photo: Photo object>]

Результирующий запрос:

In [17]: print Photo.objects.filter(tags=t1).filter(tags=t2).query
SELECT "test_photo"."id"
FROM "test_photo"
INNER JOIN "test_photo_tags" ON ("test_photo"."id" = "test_photo_tags"."photo_id")
INNER JOIN "test_photo_tags" T4 ON ("test_photo"."id" = T4."photo_id")
WHERE ("test_photo_tags"."tag_id" = 3  AND T4."tag_id" = 4 )

Обратите внимание, что каждый filter добавляет больше JOINS к запросу.

Использование аннотации приближается :

In [29]: from django.db.models import Count
In [30]: Photo.objects.filter(tags__in=[t1, t2]).annotate(num_tags=Count('tags')).filter(num_tags=2)
Out[30]: [<Photo: Photo object>]

Результирующий запрос:

In [32]: print Photo.objects.filter(tags__in=[t1, t2]).annotate(num_tags=Count('tags')).filter(num_tags=2).query
SELECT "test_photo"."id", COUNT("test_photo_tags"."tag_id") AS "num_tags"
FROM "test_photo"
LEFT OUTER JOIN "test_photo_tags" ON ("test_photo"."id" = "test_photo_tags"."photo_id")
WHERE ("test_photo_tags"."tag_id" IN (3, 4))
GROUP BY "test_photo"."id", "test_photo"."id"
HAVING COUNT("test_photo_tags"."tag_id") = 2

AND ed Q объекты не будут работать:

In [9]: from django.db.models import Q
In [10]: Photo.objects.filter(Q(tags__name='holiday') & Q(tags__name='summer'))
Out[10]: []
In [11]: from operator import and_
In [12]: Photo.objects.filter(reduce(and_, [Q(tags__name='holiday'), Q(tags__name='summer')]))
Out[12]: []

Результирующий запрос:

In [25]: print Photo.objects.filter(Q(tags__name='holiday') & Q(tags__name='summer')).query
SELECT "test_photo"."id"
FROM "test_photo"
INNER JOIN "test_photo_tags" ON ("test_photo"."id" = "test_photo_tags"."photo_id")
INNER JOIN "test_tag" ON ("test_photo_tags"."tag_id" = "test_tag"."id")
WHERE ("test_tag"."name" = holiday  AND "test_tag"."name" = summer )
101
ответ дан Hedde van der Heide 26 August 2018 в 11:33
поделиться

Это также может быть сделано путем создания динамических запросов с использованием Django ORM и некоторой магии Python:)

from operator import and_
from django.db.models import Q

categories = ['holiday', 'summer']
res = Photo.filter(reduce(and_, [Q(tags__name=c) for c in categories]))

Идея состоит в том, чтобы генерировать соответствующие объекты Q для каждой категории, а затем объединять их с помощью оператора AND в один QuerySet. Например. для вашего примера он будет равен

res = Photo.filter(Q(tags__name='holiday') & Q(tags__name='summer'))
2
ответ дан demalexx 26 August 2018 в 11:33
поделиться

Другой подход, который работает, хотя и только PostgreSQL, использует django.contrib.postgres.fields.ArrayField:

Пример скопирован из docs :

>>> Post.objects.create(name='First post', tags=['thoughts', 'django'])
>>> Post.objects.create(name='Second post', tags=['thoughts'])
>>> Post.objects.create(name='Third post', tags=['tutorial', 'django'])

>>> Post.objects.filter(tags__contains=['thoughts'])
<QuerySet [<Post: First post>, <Post: Second post>]>

>>> Post.objects.filter(tags__contains=['django'])
<QuerySet [<Post: First post>, <Post: Third post>]>

>>> Post.objects.filter(tags__contains=['django', 'thoughts'])
<QuerySet [<Post: First post>]>

ArrayField имеет некоторые более мощные функции, такие как overlap и индексные преобразования .

5
ответ дан Sander van Leeuwen 26 August 2018 в 11:33
поделиться

Если мы хотим сделать это динамически, следуйте примеру:

tag_ids = [t1.id, t2.id]
qs = Photo.objects.all()

for tag_id in tag_ids:
    qs = qs.filter(tag__id=tag_id)    

print qs
-1
ответ дан tarasinf 26 August 2018 в 11:33
поделиться
Другие вопросы по тегам:

Похожие вопросы: