根据MTM字段过滤django查询集

时间:2011-12-30 17:07:19

标签: django django-views

我正在制作一个非常轻量级的crm,用于django的非盈利组织。对此问题感兴趣的模型是:


class Human(models.Model):
    first_name = models.CharField(max_length=200)
    last_name = models.CharField(max_length=200)
    nickname = models.CharField(max_length=200, blank=True, null=True)
    middle_name = models.CharField(max_length=200, blank=True, null=True)

    def __unicode__(self):
        namestring = self.last_name+','+self.first_name
        if self.nickname:
            namestring += '('+self.nickname+')'
        elif self.middle_name:
            namestring += '('+self.middle_name+')'
        return namestring

class PhoneNumber(models.Model):
    humans = models.ManyToManyField(Human, through='HumanToPhoneNumber')
    nation_code = models.IntegerField(blank=True, null=True)
    area_code = models.IntegerField()
    local_number = models.IntegerField()

    def __unicode__(self):
        what_to_call_it = "("+str(self.area_code)+")"+str(self.local_number)
        if (self.nation_code):
            what_to_call_it = str(self.nation_code)+what_to_call_it
        return what_to_call_it


class HumanToPhoneNumber(models.Model):
    human = models.ForeignKey(Human)
    phone_number = models.ForeignKey(PhoneNumber)
    begin_date = models.DateTimeField('begin date')
    end_date = models.DateTimeField('end date', null=True, blank=True)
    active = models.BooleanField(default=True)
    preferred = models.BooleanField(default=False)
    label = models.CharField(max_length=200, blank=True, null=True)

    def __unicode__(self):
        what_to_call_it = str(self.human)
        if self.label:
            what_to_call_it += "("+self.label+")"
        return what_to_call_it

当我显示一个人的电话号码时,我只想显示仍然“活跃”的电话号码,并且还通过首选联系方式显示标记(电子邮件,humantoemail,地址, humantoaddress)。不止一个人可以拥有相同的号码,一个人可以拥有多个号码,因此它是多对多的。

对此的观点是:


def human(request, human_id):
    p = get_object_or_404(Human, pk=human_id)
    emails = p.emailaddress_set.all()
    emails.filter(emailaddress__humantoemailaddress.active=True) #this line does not work
    phone_numbers = p.phonenumber_set.all()
    addresses = p.physicaladdress_set.all()    
    return render_to_response('person.html', {'person': p, 'emails': emails, 'phone_numbers': phone_numbers, 'addresses': addresses})

我已经尝试了上面的一些变化,但我显然没有意识到我是如何访问多对多关系中的“活动”字段的。我不能将该字段放在Email,PhoneNumber或PhysicalAddress模型上,因为它可能仍然对一个人有效但对另一个人不再有效,对于“首选”也是如此。

在django视图中编写此查询的正确方法是什么?任何帮助表示赞赏。哦,我正在使用Django 1.3,以防万一。

编辑:纠正了上述错误,并尝试使用不同的过滤器对电话号码或多或少地从MTM上的Django文档中复制:

def human(request, human_id):
p = get_object_or_404(Human, pk=human_id)
emails = p.emailaddress_set.filter(humantoemailaddress__active=True) <--- does not work
phone_numbers = p.phone_number_set.filter(humantophonenumber__begin_date__gt=date(2011,1,1)) <--- does not work either
addresses = p.physicaladdress_set.all()    
return render_to_response('person.html', {'person': p, 'emails': emails, 'phone_numbers': phone_numbers, 'addresses': addresses})

我们非常感谢您的帮助,如果还有其他任何细节,请与我联系。

第二次编辑:D'哦!它有助于编辑正确的文件。我已经检查了下面的答案,实际上效果很好。

1 个答案:

答案 0 :(得分:1)

您可以使用双下划线表示法过滤连接表中的字段,例如humantophonenumber__active

例如:

p = get_object_or_404(Human, pk=human_id)
phone_numbers = p.phone_number_set.filter(humantophonenumber__active=True)

有关披头士乐队的其他示例,请查看Django docs