开发者

Returning a randomly ordered set of distinct objects from a ManyToMany relationship

I'm using Django 1.3 with Postgresql 8.4 and I've got models like the following (irrelevant stuff removed):

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)

I'm trying to get a distinct set of Service objects, filtered by attributes of linked Location objects, and ordered randomly. I tried this first:

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

...but that throws this exception:

DatabaseError: for SELECT DISTINCT, ORDER BY expressions must appear in select list

After Googling around, I discovered that to achieve this kind of result at the SQL level, you need to put the DISTINCT and the ORDER BY in separate query levels, ie: use a subquery. If I subquery a DISTINCT set of results I can randomly order them like this:

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()

Do I need to use the Manage开发者_运维技巧r.raw() method with this SQL query to get my set of model instances, or is there a simpler way to do this from within the Django API?


Depending on your exact requirements the following might work (and potentially perform better than ORDER BY Random()). I'm not sure about Postgresql, but with MySQL randomized ordering on anything but a tiny dataset is really slow.

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

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜