【问题标题】:Django query based on through table基于直通表的Django查询
【发布时间】:2022-11-12 17:43:26
【问题描述】:

我有 4 个模型,分别是内容、过滤器、ContentFilter 和用户。

用户可以查看内容。 可以使用过滤器限制内容,以便用户看不到它。

这是模型。

class Content(models.Model):
    title = models.CharField(max_length=120)
    text = models.TextField()
    filters = models.ManyToManyField(to="Filter", verbose_name=_('filter'), blank=True, related_name="filtered_content",through='ContentFilter')

class Filter(models.Model):
    name = models.CharField(max_length=255, verbose_name=_('name'), unique=True)
    added_user = models.ManyToManyField(to=User, related_name="added_user", blank=True)
    ignored_user = models.ManyToManyField(to=User, related_name="ignored_user", blank=True)
    charge_status = models.BooleanField(blank=True, verbose_name=_('charge status'))

class ContentFilter(models.Model):
    content = models.ForeignKey(Content, on_delete=models.CASCADE)
    filter = models.ForeignKey(Filter, on_delete=models.CASCADE)
    manual_order = models.IntegerField(verbose_name=_('manual order'), default=0,rst'))
    access = models.BooleanField(_('has access'))

这意味着存在 5 个内容(1,2,3,4,5)。

存在 2 个用户。 x,y

可以使用 (x) 的忽略用户创建过滤器。

1、2、3的内容与过滤器x有关系。

所以现在 X 看到 4,5 而 Y 看到 1,2,3,4,5


我现在正在做的是根据哪个用户请求找到与他们相关的过滤器。 然后查询直通表(ContentFilter)以查找用户看不到的内容,然后将它们从所有内容中排除。(这有助于大型连接)

filters = Filter.objects.filter(Q(added_user=user)|(Q(ignored_user=user))
excluded_contents = list(ContentFilter.objects.filter(filter__in=filters).values_list('id',flat=True))
contents = Contents.objects.exclude(id__in=excluded_contents)

问题

我想要一种方法,以便过滤器可以有一个顺序,并根据每个用户的顶部 ContentFilter 过滤查询集。 例如,可以使用 1 个过滤器为所有用户阻止内容 1(过滤器 x,其中被忽略的用户拥有所有用户) 但在ContentFilter 中的 manual_order 为 0。

然后在第二个过滤器中,所有收费状态为 True 的用户都可以看到此内容。(过滤 y 其中添加的用户具有所有用户且收费状态为 True。) 在ContentFilter 中,manual_order 为 1。

我想我可以使用 for 循环来检查所有内容,并根据包含该用户的过滤器选择最上面的 ContentFilter,但这既耗时又耗资源。

我不喜欢使用原始 SQL,但我不确定是否有办法使用 django orm

【问题讨论】:

    标签: django django-models django-orm


    【解决方案1】:

    我设法使用子查询解决了这个问题。

    首先,我创建一个用户所属的过滤器列表。

    filters = Filter.objects.filter(Q(added_user=user)|(Q(ignored_user=user))
    

    然后我创建一个子查询来为每个内容分配一个访问值(如果对其应用了任何过滤器。)

    current_used_filters = ContentFilter.objects.filter(Q(filter__in=user_filters),content=OuterRef('pk')).order_by('-manual_order')
    blocked_content_list = Content.objects.annotate(access=Subquery(current_used_filters.values('access')[:1])).filter(
            access=False).values_list('id', flat=True)
    

    这就提出了一个问题 如果我的任何内容没有与之关联的过滤器过滤器,那么它就不会包含在其中。 所以我过滤那些访问值为False的 这意味着该内容有一个过滤器,该过滤器具有高手动顺序,可以为该特定用户阻止它。 所以现在我有一个内容 ID 列表,现在我可以将其从所有内容中排除。 所以它会是:

    contents = Contents.objects.exclude(id__in=blocked_content_list)
    

    【讨论】:

      猜你喜欢
      • 2022-11-10
      • 1970-01-01
      • 1970-01-01
      • 2013-03-16
      • 2021-04-06
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2020-04-13
      相关资源
      最近更新 更多