【问题标题】:Filter objects by manytomany relation按多对多关系过滤对象
【发布时间】:2017-04-26 15:23:35
【问题描述】:

想不出一个按多对多关系过滤的好方法。

class Scheduler(models.Model):
    weekhours = models.ManyToManyField('WeekHour', related_name='schedulers')

    def get_active_products_by_weekhour(self,weekhour):
        return Product.objects.filter(scheduler__in=WeekHour.objects.get(hour=weekhour).schedulers.all())


class WeekHour(models.Model):
    hour = models.PositiveSmallIntegerField(verbose_name='Hour in week (0 - 7*24')

现在假设我有一个数字列表,例如:

hours = [2,4,6]

我想找到一个调度程序,它具有这组精确的WeekHour 对象和这些hour 值。

因此,当且仅当有一些设置了本周时间[WeekHour(hour=2),WeekHour(hour=4),WeekHour(hour=6)] 时,它才会返回调度程序。所以相关的 WeekHours 的数量必须与列表的大小相同。在这种情况下 3.

这可以使用 Django orm 而不是使用循环吗?

编辑:

这个怎么样?

weekhours_set = [Weekhour.objects.get(hour=x) for x in hours]
scheduler = Scheduler.objects.filter(weekhours__exact=weekhours_set)

这会返回:

TypeError: int() 参数必须是字符串或数字,而不是“列表”

【问题讨论】:

    标签: python django django-models many-to-many django-orm


    【解决方案1】:

    __exact 期望与字段类型相同的类型。

    您应该考虑使用__in,然后将operator.and_ 上的Q 表达式链接到过滤与所有相关对象的ID 有关系的精确 对象:

    import operator
    from django.db.models import Q
    
    weekhours_set = Weekhour.objects.filter(hour__in=hours).values_list('id', flat=True)
    schedulers = Scheduler.objects.filter(reduce(operator.and_, [Q(weekhours__id=id) for id in weekhours_set]))
    

    【讨论】:

    • 恐怕这不能正常工作。出于测试目的,我有两个调度程序对象。第一个有 weekhours = [WeekHour(hour=2),WeekHour(hour=4),WeekHour(hour=6)] 并且第二个有所有可能的周时间( WeekHour(hour=
    • 而且调度器是不同的(没有两个调度器具有相同的 WeekHour 集)。
    • 不幸的是,这不会返回任何东西。如果我打印 weekhours_set,它将返回 。应该是查询集吗?
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2023-03-06
    • 2020-06-18
    • 1970-01-01
    相关资源
    最近更新 更多