我有两张桌子:
class Collection(models.Model):
name = models.CharField()
class Image(models.Model):
name = models.CharField()
image = models.ImageField();
collection = models.ForeignKey(Collection)
我想从每个集合中检索第一张图片。我试过了:
image_list = Image.objects.order_by('collection.id').distinct('collection.id')
但它没有达到预期的效果:(
有什么想法吗? 感谢。
答案 0 :(得分:3)
不要使用点来分隔跨越Django中关系的字段;相反,使用双下划线约定 - 它意味着“遵循此关系来到达此字段”
这更正确:
image_list = Image.objects.order_by('collection__id').distinct('collection__id')
然而,它可能不会做你想要的。
“第一”的概念并不总是以您似乎使用它的方式应用于关系数据库。对于具有相同集合ID的图像表中的所有记录,没有“第一”或“最后”的记录 - 它们都只是记录。您可以在该表上放置另一个字段来定义特定订单,或者您可以按ID排序,或按字母顺序按名称排序,但默认情况下不会发生这些。
最适合您的方法是使用一个查询获取集合列表,然后在单独的查询中获取每个集合的单个项目:
collection_ids = Image.objects.values_list('collection', flat=True).distinct()
image_list = [
Image.objects.filter(collection__id=c)[0] for c in collection_ids
]
如果要对图像应用订单,要定义哪个是“第一个”,请按以下方式修改:
collection_ids = Image.objects.values_list('collection', flat=True).distinct()
image_list = [
Image.objects.filter(collection__id=c).order_by('-id')[0] for c in collection_ids
]
您还可以编写原始SQL - MySQL聚合具有一个有趣的属性,即未聚合的字段仍然可以出现在最终输出中,并且基本上从匹配记录集中获取随机值。这样的事情可能有用:
Image.objects.raw("SELECT image.* FROM app_image GROUP BY collection_id")
此查询应该从每个集合中获取一个图像,但您无法控制返回哪个图像。
答案 1 :(得分:0)
正如我在评论中所写,您不能在MySQL下使用distinct
的特定字段。但是,您可以通过以下方式获得相同的结果:
from itertools import groupby
all_images = Image.objects.order_by('collection__id')
images_by_collection = groupby(all_images, lambda image: image.collection_id)
image_list = sum([group for key, group in images_by_collection], [])
不幸的是,这会导致对DB的“更大”查询(检索所有图像)。
答案 2 :(得分:0)
dict([(c.id, c.image_set.all()[0]) for c in Collection.objects.all()])
这将在每个集合中创建第一个图像的字典(默认排序),由集合的id键入。但请注意,这将生成1 + N个查询,其中N是集合对象的总数。
要解决这个问题,您需要等待Django 1.4和prefetch_related
或使用类似django-batch-select的内容。
答案 3 :(得分:-1)
首先得到不同的结果,然后进行过滤。
<块引用>我觉得你应该试试这个。
image_list = Image.objects.distinct()
image_list = image_list.order_by('collection__id')