Django:我如何选择具有相同字段值的对象?

时间:2011-01-18 13:20:48

标签: django django-models

例如,我有一个这样的模型:

Class Doggy(models.Model):
    name = models.CharField(u'Name', max_length = 40)
    color = models.CharField(u'Color', max_length = 20)

我如何选择相同颜色的小狗?或者使用相同的名称:)

UPD。当然,我不知道名字或颜色。我希望......有点,按他们的价值观分组。

UPD2。我正在尝试做类似的事情,但是使用Django:

SELECT * 
FROM table 
WHERE tablefield IN ( 
 SELECT tablefield
 FROM table 
 GROUP BY tablefield  
 HAVING (COUNT(tablefield ) > 1) 
) 

UPD3。我想通过Django ORM来做,而不必迭代对象。我只想获得一个特定字段的重复值的行。

5 个答案:

答案 0 :(得分:5)

我迟到了,但你到了这里:

Doggy.objects.values('color', 'name').annotate(Count('pk'))

这将为您提供结果,其中包含您按颜色和名称分组的每只狗的数量。

答案 1 :(得分:2)

您可以使用itertools.groupby()

import operator
import itertools
from django.db import models

def group_model_by_attr(model_class, attr_name):
    assert issubclass(model_class, models.Model), \
        "%s is not a Django model." % (model_class,)
    assert attr_name in [field.name for field in Event._meta.fields], \
        "The %s field doesn't exist on model %s" % (attr_name, model_class)

    all_instances = model_class.objects.all().order_by(attr_name)
    keyfunc = operator.attrgetter(attr_name)    
    return [{k: list(g)} for k, g in itertools.groupby(all_instances, keyfunc)]

grouped_by_color = group_model_by_attr(Doggy, 'color')
grouped_by_name = group_model_by_attr(Doggy, 'name')

grouped_by_color(例如)将是[{'purple': [doggy1, doggy2], {'pink': [doggy3,]}]等词组的列表,其中doggy1,2等是Doggy个实例。

<强>更新

从您的更新中看起来您只需要每种事件类型的ID列表。我在我的ubuntu笔记本电脑上使用postgresql中的250k记录进行了测试,其中包括核心2 duo&amp; 3gb的ram,花了0.35秒(itertools.group_by用了.72秒btw)来生成dict。你提到你有900K的记录,所以这应该足够快。如果不是这样,随着记录的变化,缓存/更新应该很容易。

from collections import defaultdict

doggies = Doggy.objects.values_list('color', 'id').order_by('color').iterator()
grouped_doggies_by_color = defaultdict(list)
for color, id in doggies:
    grouped_doggies_by_color[color].append(id)

答案 2 :(得分:1)

如果你正在寻找某种颜色的狗狗 - 你会做类似的事情。

Doggy.objects.filter(color='blue')

如果你想根据当前Doggy的颜色找到Doggys

def GetSimilarColoredDoggys(self):
    return Doggy.objects.filter(color=self.color)

名称也是如此: -

def GetDoggysWithSameName(self):
    return Doggy.objects.filter(color=self.name)

答案 3 :(得分:-1)

我会更改您的数据模型,以便颜色和名称与Doggy的一对多关系如下:

class Doggy(models.Model):
    name = models.ForeignKey('DoggyName')
    color = models.ForeignKey('DoggyColor')

class DoggyName(models.Model):
    name = models.CharField(max_length=40, unique=True)

class DoggyColor(models.Model):
    color = models.CharField(max_length=20, unique=True)

现在DoggyNameDoggyColor不包含重复的名称或颜色,您可以使用它们来选择具有相同名称或颜色的狗。

答案 4 :(得分:-3)

好吧,显然,仅使用ORM无法做到这一点。

如果必须这样做,你必须使用.extra()来执行所需的SQL语句(当然,如果你使用的是SQL数据库)