список не работает в запросе - PullRequest
0 голосов
/ 28 февраля 2011

Может кто-нибудь сказать мне, почему этот запрос будет обрабатываться, только если я жестко наберу код phone_type

#model.py

class ClientPhone(models.Model):
    client = models.ForeignKey(Client, editable=False)
    ...
    phone_type = models.CharField(max_length=5, choices=PHONE_CHOICES)
    number = models.CharField(max_length=24)

# models.py

PHONE_CHOICES = (
    ('home', 'Home'),
    ('home2', 'Home 2'),
    ('mobi', 'Mobile'),
    ('mobi2', 'Mobile 2'),
    ('work', 'Work'),
    ('work2', 'Work 2'),
)

# views.py

    phones = [ClientPhone.objects.filter(client=i_clientKEY).filter(phone_type=k).latest('created') for k, v in PHONE_CHOICES]

# shell

>>> from client.models import ClientPhone
>>> phones = [ClientPhone.objects.filter(client=1).filter(phone_type=k).latest('created') for k, v in PHONE_CHOICES]
Traceback (most recent call last):
  File "<console>", line 1, in <module>
  File "/usr/local/lib/python2.6/dist-packages/django/db/models/query.py", line 395, in latest
    return obj.get()
  File "/usr/local/lib/python2.6/dist-packages/django/db/models/query.py", line 341, in get
        % self.model._meta.object_name)
DoesNotExist: ClientPhone matching query does not exist.
>>> phones = [ClientPhone.objects.filter(client=1).filter(phone_type='home').latest('created') for k, v in PHONE_CHOICES]
>>> phones
[<ClientPhone: ClientPhone object>, <ClientPhone: ClientPhone object>, <ClientPhone: ClientPhone object>, <ClientPhone: ClientPhone object>, <ClientPhone: ClientPhone object>, <ClientPhone: ClientPhone object>]

Ответы [ 2 ]

3 голосов
/ 28 февраля 2011

latest() вызывает исключение, если совпадений не найдено, поэтому, если у каждого клиента нет каждого phone_type, вы получите исключение, если у клиента нет одного из home, home2, mobi и т. Д.

Во втором примере вы всегда ищете только home, который, по-видимому, имеет действительный результат для latest().

Один метод:

latest_phones = []
for k, v in PHONE_CHOICES:
    try:
        latest_phones.append(ClientPhone.objects.filter(client=i_clientKEY, phone_type=k).latest('id'))
    except ClientPhone.DoesNotExist:
        pass 

Еще один более эффективный метод, если вас интересуют только некоторые конкретные значения из модели:

client_phone_numbers = ClientPhone.objects.filter(client=i_clientKEY)\
     .order_by('-created').values_list('phone_type', 'phone_number').distinct()

# returns list of all `phone_type` and its latest `phone_number` for this client
# if you don't need all phone types, specifically filter them in the first filter
# eg: filter(phone_type__in=['home','mobi'])
0 голосов
/ 28 февраля 2011

Вы можете использовать метод get_or_create() вместо latest(), чтобы гарантировать, что все типы телефонов находятся в базе данных.

...