You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

在Odoo QWeb电商模板中实现Isotope网格分页与筛选

Odoo QWeb集成Isotope实现产品网格筛选与分页

问题背景

我下载了一款Bootstrap电商模板,计划集成到Odoo QWeb模板系统中。当前产品网格视图的分页与筛选功能均未生效,需要借助Isotope网格完成筛选器(包含分类、子分类、品牌、价格区间)及产品网格的功能开发,现有产品网格代码如下:

<div t-attf-class="isotope-grid filter-grid cols-3 rows-1 mb-2" itemsPerPageDefault="6">
    <div class="gutter-sizer"></div>
    <div class="grid-sizer"></div>
    <!-- Product-->
    <t t-foreach="Products" t-as="prods">
        <div t-attf-class="grid-item scid{{prods.product_sub_cat_id.id}} cid{{prods.product_type_id.id}} brid{{prods.product_brand_id.id}}">
            <div class="product-card">
                <div class="product-badge text-danger">
                    <t t-esc="prods.discount" />
                    % Off
                </div>
                <a class="product-thumb" t-attf-href="/template/shop-single/{{slug(prods)}}">
                    <img t-att-src="image_data_uri(prods.first_image)" style="height: 200px;" alt="Product" />
                </a>
                <h3 class="product-title">
                    <a t-attf-href="/template/shop-single/{{slug(prods)}}">
                        <t t-esc="prods.name" />
                    </a>
                </h3>
                <h4 class="product-price">
                    <del>
                        pkr
                        <t t-esc="prods.price" />
                    </del>
                    pkr
                    <t t-esc="prods.price - ((prods.discount*prods.price)/100)" />
                </h4>
                <div class="product-buttons">
                    <button class="btn btn-outline-secondary btn-sm btn-wishlist" data-toggle="tooltip" title="Whishlist">
                        <i class="icon-heart"></i>
                    </button>

                    <form t-attf-id="fa{{prods.id}}" t-attf-action="/template/update-mycart" class="d-inline-block" method="GET">
                        <input type="hidden" t-attf-id="ia{{prods.id}}" t-att-name="product_id" t-attf-value="{{prods.id}}" title="" />
                    </form>
                    <a t-attf-id="{{prods.id}}" onclick="addCart(this)" class="btn btn-outline-primary btn-sm" data-toast="" data-toast-type="success" data-toast-position="topRight" data-toast-icon="icon-circle-check" data-toast-title="Product" data-toast-message="successfuly added to cart!">
                            Add to Cart
                        </a>
                </div>
            </div>
        </div>
    </t>
</div>

实现步骤

1. 引入Isotope依赖

下载Isotope核心库及Isotope分页插件,将JS文件放入Odoo静态资源目录,在模板中引入:

<script src="/your-static-path/isotope.pkgd.min.js"></script>
<script src="/your-static-path/isotope-pagination.min.js"></script>

2. 搭建筛选器HTML结构

在产品网格上方添加分类、子分类、品牌、价格区间筛选控件:

<!-- 筛选器容器 -->
<div class="filter-controls mb-4">
    <!-- 分类筛选 -->
    <div class="filter-group">
        <label>分类:</label>
        <button class="filter-btn active" data-filter="*">全部</button>
        <t t-foreach="ProductCategories" t-as="cat">
            <button class="filter-btn" t-att-data-filter=".cid{{cat.id}}">
                <t t-esc="cat.name"/>
            </button>
        </t>
    </div>

    <!-- 子分类筛选 -->
    <div class="filter-group">
        <label>子分类:</label>
        <button class="filter-btn active" data-filter="*">全部</button>
        <t t-foreach="ProductSubCategories" t-as="subcat">
            <button class="filter-btn" t-att-data-filter=".scid{{subcat.id}}">
                <t t-esc="subcat.name"/>
            </button>
        </t>
    </div>

    <!-- 品牌筛选 -->
    <div class="filter-group">
        <label>品牌:</label>
        <button class="filter-btn active" data-filter="*">全部</button>
        <t t-foreach="ProductBrands" t-as="brand">
            <button class="filter-btn" t-att-data-filter=".brid{{brand.id}}">
                <t t-esc="brand.name"/>
            </button>
        </t>
    </div>

    <!-- 价格区间筛选 -->
    <div class="filter-group">
        <label>价格区间:</label>
        <button class="filter-btn active" data-filter="*">全部</button>
        <button class="filter-btn" data-filter="[data-price-range='0-1000']">0-1000 PKR</button>
        <button class="filter-btn" data-filter="[data-price-range='1001-5000']">1001-5000 PKR</button>
        <button class="filter-btn" data-filter="[data-price-range='5001+']">5000+ PKR</button>
    </div>
</div>

同时修改产品网格项,添加价格区间的data属性:

<div t-attf-class="grid-item scid{{prods.product_sub_cat_id.id}} cid{{prods.product_type_id.id}} brid{{prods.product_brand_id.id}}" 
     t-att-data-price-range="
        {{ '0-1000' if prods.price - ((prods.discount*prods.price)/100) <= 1000 else 
           '1001-5000' if prods.price - ((prods.discount*prods.price)/100) <=5000 else 
           '5001+' }}">

3. 初始化Isotope与分页功能

在模板底部添加JS脚本,完成筛选绑定和分页初始化:

<script>
document.addEventListener('DOMContentLoaded', function() {
    // 初始化Isotope网格
    const grid = document.querySelector('.isotope-grid');
    const iso = new Isotope(grid, {
        itemSelector: '.grid-item',
        masonry: {
            columnWidth: '.grid-sizer',
            gutter: '.gutter-sizer'
        }
    });

    // 绑定筛选按钮事件
    document.querySelectorAll('.filter-btn').forEach(btn => {
        btn.addEventListener('click', function() {
            // 更新按钮激活状态
            document.querySelectorAll('.filter-btn.active').forEach(el => el.classList.remove('active'));
            this.classList.add('active');
            
            // 执行筛选
            const filterValue = this.getAttribute('data-filter');
            iso.arrange({ filter: filterValue });
            
            // 筛选后重置分页
            isoPagination.updateItems();
        });
    });

    // 初始化分页组件
    const isoPagination = new IsotopePagination(iso, {
        itemsPerPage: parseInt(grid.getAttribute('itemsPerPageDefault')) || 6,
        containerClass: 'isotope-pagination',
        itemClass: 'page-item',
        linkClass: 'page-link',
        activeClass: 'active',
        prevText: '上一页',
        nextText: '下一页',
        appendTo: grid.parentElement
    });
});
</script>

4. 适配Bootstrap样式(可选)

添加基础样式,让筛选器和分页组件适配Bootstrap风格:

.filter-group {
    display: inline-block;
    margin-right: 1.5rem;
    margin-bottom: 0.5rem;
}
.filter-btn {
    margin: 0 0.3rem;
    padding: 0.375rem 0.75rem;
    border-radius: 0.25rem;
    border: 1px solid #dee2e6;
    background-color: #fff;
    cursor: pointer;
    transition: all 0.2s;
}
.filter-btn.active {
    background-color: #0d6efd;
    color: #fff;
    border-color: #0d6efd;
}
.filter-btn:hover {
    background-color: #f8f9fa;
}
.isotope-pagination {
    margin-top: 2rem;
    display: flex;
    justify-content: center;
    list-style: none;
    padding-left: 0;
}
.page-item {
    margin: 0 0.25rem;
}
.page-link {
    padding: 0.5rem 0.75rem;
    border: 1px solid #dee2e6;
    border-radius: 0.25rem;
    text-decoration: none;
    color: #0d6efd;
    transition: background-color 0.2s;
}
.page-item.active .page-link {
    background-color: #0d6efd;
    color: #fff;
    border-color: #0d6efd;
}
.page-link:hover {
    background-color: #e9ecef;
}

内容的提问来源于stack exchange,提问作者Ehsan Danish

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.11 14:50:43