Django - requests repeated / inefficient

Ok, I have a Django view, for example:

@render_to('home/main.html')
def login(request):
    # also tried Client.objects.select_related().all()
    clients = Client.objects.all()
    return {'clients':clients}

And I have a template main.html, for example:

<ul>
{% for client in clients %}
<li>{{ client.full_name }}</li>
    <ul>
    {% for pet in client.pets.all %}
        <li>{{ pet.full_name }}</li>
    {% endfor %}
    </ul>
{% endfor %}
</ul>

I also print all requests at sql_queriesthe bottom of the base template. When I run this view, the following queries are executed:

SELECT `home_client`.`id`, ... FROM `home_client`;
SELECT `home_pet`.`id`, ... FROM `home_pet` WHERE `home_pet`.`client_id` = 1;
SELECT `home_client`.`id`, ... FROM `home_client` WHERE `home_client`.`id` = 1;
SELECT `home_client`.`id`, ... FROM `home_client` WHERE `home_client`.`id` = 1;
SELECT `home_pet`.`id`, ... FROM `home_pet` WHERE `home_pet`.`client_id` = 2;
SELECT `home_client`.`id`, ... FROM `home_client` WHERE `home_client`.`id` = 2; 

: ? 1 ? 2 home_client, 3 . , 3 4 100% . " " - , , Django . . .

+3
3

1 2 2 1 ?

, , Pet.full_name - , Pet, . Django ORM , Pet .

P.S. select_related , , , "--".

:, Pet.full_name , , ForeignKey :

class Client(models.Model):
    # ...
    def get_pets(self):
        for pet in self.pets.all():
            setattr(pet, '_client_cache', self)
            yield pet

... 'client' '_client_cache' - , Pet ForeignKey Pet Pet. , Django , ForeignKey, SingleRelatedObjectDescriptor, .

:

{% for pet in client.get_pets %}
...
{% endfor %}
+3

Django . . .

.

@render_to('home/main.html')
def login(request):
    # Query all clients 
    clients = Client.objects.all()
    # Assemble an in-memory table of pets
    pets = collections.defaultdict(list)
    for p in Pet.objects.all():
        pets[pet.client].append(p)
    # Create clients and pets tuples
    clientsPetTuples = [ (c,pets[c]) for c in clients ]
    return {'clientPets': clientsPetTuples}

, .

, SQL. , , , SQL.

SQL, .

+7

try using Client.objects.all (). select_related ()

It automatically also caches related models in a single database query.

+4
source

Source: https://habr.com/ru/post/1703400/


All Articles