【问题标题】:How to slice items generated from a forloop with conditionals in django如何在 django 中使用条件对 for 循环生成的项目进行切片
【发布时间】:2020-12-20 14:56:38
【问题描述】:

我有一个类别列表以及一个产品列表,我的模板是这样一种方式,即它具有类别部分,每个部分都显示属于所述类别的产品。我为类别创建了一个 for 循环,以便轻松显示我创建的每个类别的类别部分。然后,我继续为具有条件的 forloop 类别中的产品创建一个 forloop,以便在产品显示在其类别部分下之前将产品与其实际类别匹配。如何对生成的产品进行切片以限制显示的产品数量

模型.py


class Category(models.Model):
    name = models.CharField(max_length=120)
    image_263x629 = models.ImageField(upload_to='cat_imgs')
    image_263x629_2 = models.ImageField(upload_to='cat_imgs')
    image_263x629_3 = models.ImageField(upload_to='cat_imgs')
    img_array = [image_263x629, image_263x629_2, image_263x629_3]
    description = models.CharField(max_length=250)

    def __str__(self):
        return self.name

class SubCategory(models.Model):
    name = models.CharField(max_length=200)
    description = models.CharField(max_length=300)
    category = models.ForeignKey(Category, on_delete=models.CASCADE)

    def __str__(self):
        return self.name

    #def get_absolute_url(self):
    #   return reverse('subcat_detail', args=[str(self.id)])    

class Product(models.Model):
    name = models.CharField(max_length=120)
    price = models.FloatField()
    image_182x182 = models.ImageField(upload_to='pdt_imgs/')
    image_1200x1200 = models.ImageField(upload_to='pdt_imgs/alt_imgs/')
    image_600x600 = models.ImageField(upload_to='pdt_imgs/alt_imgs/')
    image_600x600_2 = models.ImageField(upload_to='pdt_imgs/alt_imgs/')
    image_300x300 = models.ImageField(upload_to='pdt_imgs/alt_imgs/')
    img_array = [image_1200x1200, image_600x600, image_600x600_2]
    sku = models.IntegerField()
    available = models.BooleanField(default=True)
    discount = models.IntegerField(default = 0)
    description = models.CharField(max_length=120, blank=True, null=True)
    brand = models.CharField(max_length=120, blank=True, null=True)
    category = models.ForeignKey(SubCategory, on_delete=models.CASCADE)
    seller = models.ForeignKey(Seller, on_delete=models.CASCADE)

观看次数

class HomePageView(ListView):
    model = SubCategory
    template_name = 'home.html'
    queryset = SubCategory.objects.all()



    def get_context_data(self, **kwargs):
        context = super(HomePageView, self).get_context_data(**kwargs)
        context['products'] = Product.objects.all()
        context['pdts'] = Product.objects.order_by('?')[:12]
        context['categories'] = Category.objects.all()
        context['subcategories'] = SubCategory.objects.all()
        return context

模板

    {% for category in categories %}
        <div class="ps-block--products-of-category">
          <div class="ps-block__categories">
            <h3>{{ category.name }}</h3>
            <ul>
              {% for subcategory in subcategories %}
              {% if subcategory.category.name == category.name %}
                <li><a href="{% url 'subcat_detail' subcategory.id %}">{{ subcategory.name }}</a></li>
              {% endif %}  
              {% endfor %}
            </ul><a class="ps-block__more-link" href="{% url 'cat_detail' category.id %}">View All</a>
          </div>
          <div class="ps-block__slider">
            <div class="ps-carousel--product-box owl-slider" data-owl-auto="true" data-owl-loop="true"
              data-owl-speed="7000" data-owl-gap="0" data-owl-nav="true" data-owl-dots="true" data-owl-item="1"
              data-owl-item-xs="1" data-owl-item-sm="1" data-owl-item-md="1" data-owl-item-lg="1" data-owl-duration="500"
              data-owl-mousedrag="off">
              <a href="#"><img src="{{ category.image_263x629.url }}" alt=""></a>
              <a href="#"><img src="{{ category.image_263x629_2.url }}" alt=""></a>
              <a href="#"><img src="{{ category.image_263x629_3.url }}" alt=""></a>
            </div>
          </div>
          <div class="ps-block__product-box">
              {% for product in products %}
                {% if product.category.category.name == category.name  %}
                  <div class="ps-product ps-product--simple">
                    <div class="ps-product__thumbnail"><a href="{% url 'pdt_detail' product.id %}"><img src="{{ product.image_300x300.url }}"
                          alt=""></a>
                      {% if product.discount > 0 %}  
                        <div class="ps-product__badge">-{{ product.discount }}%</div>
                      {% endif %}
                      {% if product.available == False %}
                        <div class="ps-product__badge out-stock">Out Of Stock</div>
                      {% endif %}
                      
                    </div>
                    <div class="ps-product__container">
                      <div class="ps-product__content" data-mh="clothing"><a class="ps-product__title"
                          href="{% url 'pdt_detail' product.id %}">{{ product.name }}</a>
                        <div class="ps-product__rating">
                          <select class="ps-rating" data-read-only="true">
                            <option value="1">1</option>
                            <option value="1">2</option>
                            <option value="1">3</option>
                            <option value="1">4</option>
                            <option value="2">5</option>
                          </select><span>01</span>
                        </div>
                        <p class="ps-product__price sale">UGX{{ product.price }}</p>
                      </div>
                    </div>
                  </div>
                {% endif %}  
              {% endfor %}
          </div>
        </div>
      {% endfor %}

【问题讨论】:

  • 请在模板中进行not过滤。您应该在视图中进行过滤。

标签: django


【解决方案1】:

不要在模板中过滤。您应该在视图中进行过滤。模板实现渲染逻辑,而不是业务逻辑*。

您可以在视图中过滤和切片:

def my_view(request):
    # …
    products = Product.objects.filter(category__name='specified category')[:10]
    context = {
        'products': products
    }
    return render(request, 'my_template.html', context)

这不仅是过滤的地方,而且效率更高,因为我们这里将在数据库端进行过滤和切片。通常,数据库可以更有效地执行此操作,并且它还限制了从数据库到 Django/Python 层的带宽。

注意(基于@SLDem's comment):

如果您的目标是过滤儿童,您可以使用Prefetch object [Django-doc]。事实上,假设我们有一个QuerySetCategorys,我们只想保留可用的Products,我们可以使用:

from django.db.models import Prefetch

categories = Category.objects.prefetch_related(
    Prefetch(
        'product_set',
        Product.objects.filter(available=True),
        to_attr='available_products'
    )
)

然后在模板中我们可以使用:

{% for category in categories %}
    {% for product in category.available_products %}
        …
    {% endfor %}
{% endfor %}

【讨论】:

  • 如果我希望呈现父对象列表并为每个父对象呈现子对象列表,如何在不过滤模板中的子对象的情况下实现它?
  • @SLDem:您可以使用Prefetch 对象:docs.djangoproject.com/en/dev/ref/models/querysets/…
  • @SLDem:我通过一个示例扩展了答案,例如如何根据Category 过滤可用产品。
  • 漂亮,非常感谢,现在就用这个​​代替:)
  • 我在模板中进行了过滤,因为我的模板中代码的实际结构采用以下格式上述代码也在 a for 循环中遍历类别列表,因此过滤器用于将产品与类别项匹配
猜你喜欢
  • 2021-03-28
  • 2021-10-11
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2017-12-27
相关资源
最近更新 更多