2016-07-18 4 views
0

У меня есть немного каверзный вопрос (я думаю)Джанго фильтра ManyToManyField QuerySet

У меня есть модель под названием Post (models.Model): с многим ко многим соотношение, которое называется акциями

class Post(models.Model): 
    account = models.ForeignKey(Account, related_name="account") 
    shares = models.ManyToManyField(Account, related_name="shares_account", through='Share') 
    ... 

class Share(models.Model): 
    post = models.ForeignKey(Post) 
    account = models.ForeignKey(Account) 

    new = models.BooleanField(default=True) 
    ... 

Теперь я нужен способ фильтрации сообщений с точными «х» акциями .. например. У меня есть сообщение с идентификатором «222», это сообщение делится с идентификатором учетной записи 12, 13, 16. Теперь я хочу фильтровать все сообщения, совместно используемые с идентификаторами 12, 13 и 16 учетной записи.

Как это сделать? Моя плохая попытка, как так ::;)

posts = Post.objects.filter(reduce(and_, [Q(shares=aid) for aid in account_ids])) 
+0

Вам нужно те сообщения, которые разделяются с числом «х» (то есть, счет равен x), или вам нужны те сообщения, которые специально используются для учетных записей, которые включают в себя только идентификаторы 12, 13 и 16 учетной записи или 12,13,16 и более, но должны иметь 12,13 и 16 в нем.? –

+0

Ох ... извините ... ТОЛЬКО счета с 12,3 и 16 .., если есть больше, это будет другая группа .. .. так всегда точная доля – pkdkk

ответ

0

Я полагаю, что это должно работать для вас.

Post.objects.annotate(cc=Count('shares')).filter(cc=3).filter(Q(shares__id=12) & Q(shares__id=13) & Q(shares__id=16)) 

Смотреть это ->Django ManyToMany filtering by set size or member in the set

+0

Не могу заставить ее работать. здесь есть простая версия. >>> Post.objects.filter (Q (shares__id = 13) & Q (shares__id = 12)) [] >>> [s.id для s в Post.objects .get (id = 2308) .shares.all()] [13, 12] – pkdkk

+0

возвращает [] ... но если я вызываю сообщение с акциями 12,13 .. то он показывает список с идентификаторами – pkdkk

+0

Но я полагаю, что если вы не включите фильтр подсчета, тогда ваш результат будет содержать те сообщения, которые будут совместно использоваться с идентификаторами 12, 13, 16 и более, а также по мере того, как вы запрашиваете фильтрацию тех POSTS, которые делятся с 12, 13 и 16. Нигде он не отфильтровывает те сообщения, которые имеют именно эти три acco и не более. –

0

Это, как добиться этого с reduce

post_qs = Post.objects.all() 
post_qs = reduce(lambda posts, share: posts.filter(shares=share), account_ids, post_qs) 

который я бы, вероятно, сделать его более многократного использования таким образом:

class PostQuerySet(models.QuerySet): 

    def having_shares(self, share_ids): 
     return reduce(lambda posts, share: posts.filter(shares=share), share_ids, self) 

class Post(models.Model): 
    ... 

    objects = PostQuerySet.as_manager(


#usage 
posts = Post.objects.all().having_shares(share_ids)