簡體   English   中英

Django排除對同一模型的多個外鍵的過濾器

[英]Django exclude filter on multiple foreign keys to the same model

我正在嘗試基於多個字段上的嵌套包含過濾查詢集。 一個領域起作用,而另一領域卻不起作用

這是我模型的簡短版本:

class Shift(models.Model):
    users = models.ManyToManyField(User, blank=True)
    potential_users = models.ManyToManyField(User, blank=True, related_name='potential_users')

我想對其進行過濾,以使用戶不在用戶中,也不在潛在用戶屬性中。 我在queryset上使用此exclude函數:

queryset = Shift.objects.exclude(users__id__contains=self.request.user.id, potential_users__id__contains=self.request.user.id)

我也嘗試鏈接排除:

queryset = Shift.objects.exclude(users__id__contains=self.request.user.id).exclude(potential_users__id__contains=self.request.user.id)

當用戶處於班次的用戶屬性中時,我沒有得到任何預期的班次。 但是,當用戶處於潛在用戶屬性中時,我確實可以轉移。

潛在用戶

當用戶處於potential_users中時。 在查詢集生成后,我在調試執行器中運行此命令:

self.request.user.id == queryset[0].potential_users.all()[0].id

我得到True ,這應該是不可能的,因為它在排除中。 我懷疑這與引用相同外鍵模型的兩個屬性有關

在用戶中

當我在users屬性中對users執行相同的過濾時,我得到的索引超出范圍,這是很好的,因為這意味着它沒有檢索到班次。 這是預期的。 這是我運行的檢查:

self.request.user.id == queryset[0].users.all()[0].id

詢問

這是完整的查詢集:

Shift.objects.annotate(amount_users=Count('users')).filter(show_on_market=True, amount_users__lt=F('amount_of_employees'), start__week=self.request.query_params['week'], start__year=self.request.query_params['year'], start__gt=datetime.datetime.now()).exclude(users__id__contains=self.request.user.id, potential_users__id__contains=self.request.user.id)

這是Django運行的查詢

SELECT `shift_shift`.`id`, `shift_shift`.`title`, `shift_shift`.`start`, `shift_shift`.`end`, `shift_shift`.`amount_of_minutes`, `shift_shift`.`amount_of_employees`, `shift_shift`.`employment_agency_id`, `shift_shift`.`client_id`, `shift_shift`.`store_id`, `shift_shift`.`description`, `shift_shift`.`show_on_market`, `shift_shift`.`repeat_shift_id`, `shift_shift`.`is_repeat`, COUNT(`shift_shift_users`.`user_id`) AS `amount_users` FROM `shift_shift` LEFT OUTER JOIN `shift_shift_users` ON (`shift_shift`.`id` = `shift_shift_users`.`shift_id`) WHERE (`shift_shift`.`is_repeat` = False AND `shift_shift`.`show_on_market` = True AND `shift_shift`.`start` > 2019-02-11 14:54:28.462725 AND WEEK(`shift_shift`.`start`, 3) = 7 AND `shift_shift`.`start` BETWEEN 2019-01-01 00:00:00 AND 2019-12-31 23:59:59.999999 AND NOT (`shift_shift`.`id` IN (SELECT U1.`shift_id` FROM `shift_shift_users` U1 WHERE U1.`user_id` LIKE BINARY %df6c3f22-b3c2-40af-81c9-9a689083bd15%)) AND NOT (`shift_shift`.`id` IN (SELECT U1.`shift_id` FROM `shift_shift_potential_users` U1 WHERE U1.`user_id` LIKE BINARY %df6c3f22-b3c2-40af-81c9-9a689083bd15%))) GROUP BY `shift_shift`.`id`, `shift_shift`.`amount_of_employees` HAVING COUNT(`shift_shift_users`.`user_id`) < (`shift_shift`.`amount_of_employees`) ORDER BY `shift_shift`.`start` ASC

有人知道我在做什么錯嗎?

您的問題的簡單答案是:

from django.db.models import Q

user_id = self.request.user.id
queryset = Shift.objects.exclude(
    Q(users__id__contains=user_id) | Q(potential_users__id__contains=user_id
)

如果我正確理解了您的意圖,即: not (in users) and not (in potential users)可以更改為: not (in users or in potential users) ,則應使用排除鏈接而不是單次呼叫,即:

queryset = Shift.objects.exclude(
    users__id__contains=self.request.user.id,
).exclude(
    potential_users__id__contains=self.request.user.id
)

嘗試這個:

from django.db.models import Q
queryset = Shift.objects.exclude(Q(users__id__in=[self.request.user.id]) & Q(potential_users__id__in=[self.request.user.id]))
  • 僅將__contains用於字符串檢查。 嘗試使用__in=[Array]語法檢查元素是否存在於多面。
  • 使用Q()可以合並多個查詢( | = OR, & = AND)
  • 您不應該鏈接多個filter()/ exclude(),因為它的計算效率較低。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM