Вот два примера моделей Django. Обратите особое внимание на метод has_pet.
class Person(models.Model):
name = models.CharField(max_length=255)
def has_pet(self):
return bool(self.pets.all().only('id'))
class Pet(models.Model):
name = models.CharField(max_length=255)
owner = models.ForeignKey(Person, blank=True, null=True, related_name="pets")
Проблема в том, что метод has_pet всегда генерирует запрос. Если вы сделаете что-то вроде этого.
p = Person.objects.get(id=1)
if p.has_pet():
...
Тогда вы действительно будете выполнять дополнительный запрос, чтобы проверить, есть ли у одного человека домашнее животное. Это большая проблема, если вам нужно проверить несколько человек. Он также будет генерировать запросы, если используется в шаблонах, подобных этому.
{% for person in persons %}
{% if person.has_pet %}
{{ person.name }} owns a pet
{% else %}
{{ person.name }} is petless
{% endif %}
{% endfor %}
В этом примере фактически будет выполняться дополнительный запрос для каждого человека в наборе запросов people во время рендеринга шаблона.
Есть ли способ сделать это с помощью всего одного запрос или хотя бы менее одного дополнительного запроса на человека? Возможно, есть другой способ спроектировать это, чтобы полностью избежать проблемы.
Я подумал о добавлении BooleanField в Person и обновлении этого поля при сохранении или удалении питомца. Это действительно правильный путь?
Кроме того, я уже правильно настроил memcached, поэтому эти запросы выполняются только в том случае, если результаты еще не кэшированы. Я хочу в первую очередь удалить запросы для еще большей оптимизации.