使用prefetch_related之后仍然面对n + 1

时间:2019-01-18 10:29:27

标签: django django-models

即使使用prefetch_related,我也面临着多个重复的数据库调用。 这是我的观点:

def index(request):
    product_qs = Product.objects.filter(shop_type='Grocery', featured=True, hide=False)
        product_list = product_qs.prefetch_related('image', 'size_list').order_by('ranking')
        products = terminator(request, product_list, 25)   // reusable paginator!
    context = {'categories': categories, 'products': products}
    return render(request, 'grocery/index.html', context)

这是我的模特:

class ProductImage(models.Model):
    image = models.ImageField(upload_to='shop/product')
    color = models.BooleanField(default=False)
    image_thumbnail_index = ImageSpecField(source='image',
                                           processors=[ResizeToFill(308, 412)],
                                           format='JPEG',
                                           options={'quality': 100})
    created_at = models.DateTimeField(auto_now_add=True)
    updated_at = models.DateTimeField(auto_now=True)

class Product(models.Model):
    shop_type = models.CharField(choices=shop_options, max_length=40)
    name = models.CharField(max_length=200, unique=True)
    image = models.ManyToManyField(ProductImage)
    category = TreeForeignKey('Category', null=True, blank=True, on_delete=models.PROTECT)
    slug = models.SlugField(max_length=200, db_index=True)
    featured = models.BooleanField(default=False)
    size = models.BooleanField(default=False)
    size_list = models.ManyToManyField(SizeList)
    available = models.BooleanField(default=True)  # out of stock ?
    hide = models.BooleanField(default=False)  # archive a product
    ranking = models.PositiveIntegerField()
    created_at = models.DateTimeField(auto_now_add=True)
    updated_at = models.DateTimeField(auto_now=True)

和模板:

<figure class="product-image-container">
    <a href="#" class="product-image">
        <img src="{{ product.image.first.image_thumbnail_index.url }}" alt="{{ products.name }}">
    </a>
    <a href="{% url 'grocery_quickview' %}?product={{ product.name }}" class="btn-quickview">{% trans 'Quickview' %}</a>
</figure>
<div class="product-details">
    <h2 class="product-title">
        <a href="/grocery/product/{{ product.slug }}">
            {% if LANGUAGE_CODE == 'en' %}
                {{ product.name }}
            {% else %}
                {{ product.name_bn }}
            {% endif %}
        </a>
    </h2>
    <div class="price-box">
        <span class="product-price">
            {% if LANGUAGE_CODE == 'en' %}
                ৳ {{ product.price }}
            {% else %}
                ৳ {{ product.price_bn }}
            {% endif %}
        </span>
    </div><!-- End .price-box -->

sql调用的屏幕截图: enter image description here

1 个答案:

答案 0 :(得分:1)

由于您已经预取了ProductImage对象,因此可以使用以下预取对象:{% with product.image.all|first as image %}{{ image.image_thumbnail_index.url }}(% endwith %}。 (虽然调用first()时最后使用LIMIT 1进行了额外的查询。)