Вот мои модели:Джанго QuerySet на несколько внешних ключей с использованием prefetch_related
class Owner():
last_name = models.CharField(max_length=30)
...
class Species():
species_code = models.CharField(max_length=10)
...
class Pet():
client = models.ForeignKey(Owner, related_name='pet_fk')
species = models.ForeignKey(Species)
....
Я хочу, чтобы перечислить всех владельцев и их питомцев. У некоторых владельцев нет домашних животных, у других их много.
Если найдено домашнее животное, я хочу аннотировать дополнительное «временное» поле css_species_class
объекту этого животного. Это поле будет возвращать «собака», если вид_код для модели для животных «CANINE» или «лошадь», если «EQUINE» и т. Д.
Поле «временное» необходимо из-за многоязычности сайта и значения css_species_class
требуется, чтобы вытащить соответствующие значки символов в шаблоне. Я не могу использовать значение, хранящееся напрямую, поэтому мне нужно вставить определенное значение, чтобы оно соответствовало значению, ожидаемому глифами.
Что-то вроде:
Owner: John Smith
Pet: Saag (css_species_class='dog')
Pet: Brinjal (css_species_class='cat')
Pet: Baji (css_species_class='dog')
Owner: Sue Smith
Pet: none
Owner: Clare Smith
Pet: Aloo (css_species_class='horse')
Мой шаблон что-то вроде этого:
{% for owner in owners %}
<tr>
<td>{{ owner.first_name }} {{ owner.last_name }}</td>
<td> <!-- loop over pet objects -->
{% for pet in owner.pet_fk.all %}
<div>
....
<span class="glyphicons glyphicons-{{ pet.css_species_class }}"></span>
....
</div>
{% endfor pet %}
</td>
</tr>
{% endfor %}
Итак, вот моя первая попытка в растворе:
class OwnerListView(ListView):
template_name = 'visitors/owner_list.html'
context_object_name = 'owners'
paginate_by = 50
def get_queryset(self):
owners_with_pets = Owner.objects.filter(pet_fk__isnull=False).prefetch_related('pet_fk').distinct()
# logic goes here to loop over pets
# and assign 'css_species_class' temp field
owners_without_pets = Owner.objects.filter(pet_fk__isnull=True).prefetch_related('pet_fk').distinct()
Then 'слияния' два запроса:
result_list = sorted(
chain(owners_with_pets, owners_without_pets),
key=attrgetter('last_name'))
return result_list
Это «работает» для небольшого числа владельцев, но если я тестирую с реальным числом (около 4000), я получаю «слишком много ошибок в переменной sql».
Первоначально я попытался сделать это в одном запросе (прежде чем решить разбить его на два запроса), но это не так эффектно и для большего числа клиентов.
Может ли кто-нибудь любезно дать мне немного указания относительно того, как наилучшим образом подойти к этому? Огромное спасибо.
Это сработало красиво, спасибо. –