从ManyToMany关系返回一组随机排序的不同对象

时间:2011-08-30 13:19:40

标签: django django-models django-queryset

我正在使用带有Postgresql 8.4的Django 1.3,我有以下模型(删除了无关的内容):

class Service(models.Model):
    name = models.CharField(max_length=80)

class Location(models.Model):
    name = models.CharField(max_length=80)
    services = models.ManyToManyField(Service, through='LocalService')

class LocalService(models.Model):
    location = models.ForeignKey(Location)
    service = models.ForeignKey(Service)

我正在尝试获取一组不同的Service对象,按链接的Location对象的属性进行过滤,并随机排序。我先试了一下:

Service.objects.filter(location__name__icontains='o').distinct().order_by('?')

...但是这引发了这个异常:

  

DatabaseError:对于SELECT DISTINCT,必须出现ORDER BY表达式   在选择列表中

在谷歌搜索之后,我发现要在SQL级别实现这种结果,您需要将DISTINCT和ORDER BY放在单独的查询级别中,即:使用子查询。如果我查询了一组DISTINCT结果,我可以按照这样的方式随机排序:

SELECT * 
FROM (
    SELECT DISTINCT s.*
    FROM profile_service s
    JOIN profile_localservice ls
    ON ls.service_id = s.id
    JOIN profile_location l
    ON ls.location_id = l.id
    WHERE l.name LIKE '%o%'
) as temptable
ORDER BY RANDOM()

我是否需要在此SQL查询中使用Manager.raw()方法来获取我的模型实例集,或者是否有更简单的方法从Django API中执行此操作?

1 个答案:

答案 0 :(得分:1)

根据您的具体要求,以下内容可能有效(并且可能比ORDER BY Random()表现更好)。我不确定Postgresql,但MySQL的随机排序除了一个很小的数据集真的很慢。

services = list(Service.objects.filter(location__name__icontains='o').distinct())
random.shuffle(services)