• django的prefetch()


    prefetch()类方法:

    prefetch_related, on the other hand, does a separate lookup for each relationship, and does the 'joining' in Python. This allows it to prefetch many-to-many and many-to-one objects, which cannot be done using
    For example, suppose you have these models

    from django.db import models
    
    class Topping(models.Model):
        name = models.CharField(max_length=30)
    
    class Pizza(models.Model):
        name = models.CharField(max_length=50)
        toppings = models.ManyToManyField(Topping)
    
        def __str__(self):
            return "%s (%s)" % (
                self.name,
                ", ".join(topping.name for topping in self.toppings.all()),
            )
    and run:

    class Restaurant(models.Model):
        pizzas = models.ManyToManyField(Pizza, related_name='restaurants')
        best_pizza = models.ForeignKey(Pizza, related_name='championed_by', on_delete=models.CASCADE)
    >>> Pizza.objects.all() ["Hawaiian (ham, pineapple)", "Seafood (prawns, smoked salmon)"...

    The problem with this is that every time Pizza.__str__() asks for self.toppings.all() it has to query the database, so Pizza.objects.all() will run a query on the Toppings table for every item in the Pizza QuerySet.  

    也就是说,上面的代码中每一次调用__str__(),又要多一次查询,而不是一次all()查询。

    prefetch()可以只用两次查询,不是通过外键关联一次查询的方式。

    >>> Pizza.objects.all().prefetch_related('toppings')  

    原理是,prefetch()将其查到的结果存到了缓存区,并做好了关联。

    也可以多次连表

     Restaurant.objects.prefetch_related('pizzas__toppings')

    另外,prefetch可以通过Prefetch对象,实现自定义的查询。

    >>> vegetarian_pizzas = Pizza.objects.filter(vegetarian=True)
    >>> Restaurant.objects.prefetch_related(
    ...     Prefetch('pizzas', to_attr='menu'),
    ...     Prefetch('pizzas', queryset=vegetarian_pizzas, to_attr='vegetarian_menu'))
    

     需要注意的是。有一些函数会清空prefetch()存下的数据

    Remember that, as always with QuerySets, any subsequent chained methods which imply a different database query will ignore previously cached results, and retrieve data using a fresh database query. So, if you write the following:

    >>> pizzas = Pizza.objects.prefetch_related('toppings')
    >>> [list(pizza.toppings.filter(spicy=True)) for pizza in pizzas]
    

    ...then the fact that pizza.toppings.all() has been prefetched will not help you. The prefetch_related('toppings') implied pizza.toppings.all(), but pizza.toppings.filter() is a new and different query. The prefetched cache can't help here; in fact it hurts performance, since you have done a database query that you haven't used. So use this feature with caution!

    Also, if you call the database-altering methods add()remove()clear() or set(), onrelated managers, any prefetched cache for the relation will be cleared.

  • 相关阅读:
    选择排序
    插入排序
    洗牌算法
    访问性模式
    策略模式
    mysql EXPLAIN Join Types 手册解释 及数据实操
    Nginx Location和Rewrite总结
    json_decode 解析带BOM头文件错误
    laravel 集成 swagger插件
    php S3
  • 原文地址:https://www.cnblogs.com/yuanji2018/p/9906309.html
Copyright © 2020-2023  润新知