Фильтрация набора запросов django на основе поля MTM - PullRequest
1 голос
/ 30 декабря 2011

Я делаю очень легкую 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, в случае, если это имеет значение.

Редактировать: исправлено опечатка в вышеприведенном, плюс пробовал другой фильтр по номеру телефона, более или менее точно скопированный из документации Django на MTM:

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'Oh!Это помогает редактировать правильный файл.Я проверил ответ ниже, который на самом деле работает просто отлично.

1 Ответ

1 голос
/ 30 декабря 2011

Вы можете фильтровать поля в объединяемой таблице, используя двойное подчеркивание, например, humantophonenumber__active.

Например:

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

Дополнительные примеры на основе Beatles можно найти в Django docs .

...