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

新手求教:如何在Django中实现品牌筛选与价格升降排序?

嘿,作为Django新手能想到要做筛选排序功能,已经迈出了很棒的一步!我来一步步教你实现你要的品牌/厂商筛选+价格排序,顺便给你讲讲Django里处理这类需求的通用思路~

一、先实现你的具体需求(品牌筛选 + 价格排序)

我们从视图层和模板层两部分来写,假设你的商品模型是Product,包含brand_name(品牌/厂商)、price(价格)这些字段。

1. 视图层处理逻辑

在你的app的views.py里写列表视图,核心是通过request.GET获取用户的筛选和排序参数,然后链式操作QuerySet:

from django.shortcuts import render
from .models import Product

def product_list(request):
    # 先拿到所有商品的基础查询集(Django的QuerySet是惰性的,不会立刻查数据库)
    products = Product.objects.all()

    # 1. 处理品牌/厂商筛选
    selected_brand = request.GET.get('brand')
    if selected_brand:
        # 过滤出对应品牌的商品,这里的字段名要和你模型里的一致
        products = products.filter(brand_name=selected_brand)

    # 2. 处理价格排序
    selected_sort = request.GET.get('sort', 'price_low')  # 默认按价格从低到高
    # 定义排序规则的白名单,防止用户传入非法参数导致错误
    sort_rules = {
        'price_low': 'price',       # 正序:价格从低到高
        'price_high': '-price'      # 倒序:价格从高到低
    }
    # 只处理白名单内的排序选项
    if selected_sort in sort_rules:
        products = products.order_by(sort_rules[selected_sort])

    # 准备模板需要的数据:所有可选的品牌(去重)、选中的筛选/排序参数
    all_brands = Product.objects.values_list('brand_name', flat=True).distinct()

    context = {
        'products': products,
        'all_brands': all_brands,
        'selected_brand': selected_brand,
        'selected_sort': selected_sort
    }
    return render(request, 'product_list.html', context)

2. 模板层渲染界面

在模板product_list.html里,我们要做一个筛选表单+排序选项,同时保留用户已经选中的参数(比如选了品牌后排序,不会丢失品牌筛选条件):

<!-- 筛选和排序表单 -->
<form method="get">
    <!-- 品牌下拉框 -->
    <div>
        <label>选择品牌:</label>
        <select name="brand" onchange="this.form.submit()">
            <option value="">全部品牌</option>
            {% for brand in all_brands %}
                <option value="{{ brand }}" {% if brand == selected_brand %}selected{% endif %}>
                    {{ brand }}
                </option>
            {% endfor %}
        </select>
    </div>

    <!-- 价格排序下拉框 -->
    <div>
        <label>价格排序:</label>
        <select name="sort" onchange="this.form.submit()">
            <option value="price_low" {% if selected_sort == 'price_low' %}selected{% endif %}>
                从低到高
            </option>
            <option value="price_high" {% if selected_sort == 'price_high' %}selected{% endif %}>
                从高到低
            </option>
        </select>
    </div>
</form>

<!-- 商品列表展示 -->
<div class="product-list">
    {% for product in products %}
        <div class="product-item">
            <h3>{{ product.name }}</h3>
            <p>品牌:{{ product.brand_name }}</p>
            <p>价格:¥{{ product.price }}</p>
        </div>
    {% empty %}
        <p>没有找到符合条件的商品哦~</p>
    {% endfor %}
</div>
二、Django中排序与筛选的通用方法

上面是针对你需求的具体实现,接下来讲几个通用思路,以后遇到类似需求都能用:

1. 利用QuerySet的链式调用

Django的QuerySet支持链式调用filter()、exclude()、order_by()等方法,而且是惰性执行的——直到你真正需要数据(比如模板里遍历)的时候才会去查数据库,所以不用担心多次调用会多查库,性能很友好。

2. 封装可复用的逻辑(Mixin模式)

如果你的项目里多个页面都需要筛选排序,可以写一个Mixin类,把通用逻辑抽出来,让视图继承它:

class SortFilterMixin:
    # 子类需要重写的配置
    filter_fields = []  # 需要支持筛选的字段,比如['brand_name', 'category']
    sort_mapping = {}   # 排序规则映射,比如{'price_low': 'price', 'price_high': '-price'}
    default_sort = ''   # 默认排序选项

    def get_queryset(self):
        queryset = super().get_queryset()
        # 处理筛选
        for field in self.filter_fields:
            value = self.request.GET.get(field)
            if value:
                queryset = queryset.filter(**{field: value})
        # 处理排序
        sort_option = self.request.GET.get('sort', self.default_sort)
        if sort_option in self.sort_mapping:
            queryset = queryset.order_by(self.sort_mapping[sort_option])
        return queryset

    def get_context_data(self, **kwargs):
        context = super().get_context_data(**kwargs)
        # 把选中的筛选/排序参数传到模板
        for field in self.filter_fields:
            context[f'selected_{field}'] = self.request.GET.get(field)
        context['selected_sort'] = self.request.GET.get('sort', self.default_sort)
        return context

然后你的视图就可以这样写,非常简洁:

from django.views.generic import ListView
from .models import Product
from .mixins import SortFilterMixin

class ProductListView(SortFilterMixin, ListView):
    model = Product
    template_name = 'product_list.html'
    filter_fields = ['brand_name']
    sort_mapping = {'price_low': 'price', 'price_high': '-price'}
    default_sort = 'price_low'

3. 永远做参数合法性校验

绝对不要直接把用户传入的参数放到filter()或order_by()里,比如不要写products.order_by(request.GET.get('sort'))——如果用户传入恶意参数,可能会导致SQL注入或者程序报错。一定要像前面那样用白名单映射,只处理你预先定义好的参数。

4. 复杂筛选用表单类验证

如果筛选条件比较复杂(比如价格范围、多条件组合),可以用Django的Form类来处理参数验证,这样更规范,也更容易处理错误提示:

from django import forms

class ProductFilterForm(forms.Form):
    brand = forms.CharField(required=False)
    min_price = forms.DecimalField(required=False, min_value=0)
    max_price = forms.DecimalField(required=False, min_value=0)
    sort = forms.ChoiceField(
        choices=[('price_low', '从低到高'), ('price_high', '从高到低')],
        required=False,
        initial='price_low'
    )

然后在视图里用这个表单:

def product_list(request):
    form = ProductFilterForm(request.GET)
    products = Product.objects.all()
    if form.is_valid():
        cleaned_data = form.cleaned_data
        # 处理品牌筛选
        if cleaned_data['brand']:
            products = products.filter(brand_name=cleaned_data['brand'])
        # 处理价格范围
        if cleaned_data['min_price']:
            products = products.filter(price__gte=cleaned_data['min_price'])
        if cleaned_data['max_price']:
            products = products.filter(price__lte=cleaned_data['max_price'])
        # 处理排序
        sort_option = cleaned_data['sort'] or 'price_low'
        sort_rules = {'price_low': 'price', 'price_high': '-price'}
        products = products.order_by(sort_rules[sort_option])
    
    context = {'products': products, 'form': form}
    return render(request, 'product_list.html', context)

模板里直接渲染表单就行,Django会自动保留用户的选中值:

<form method="get">
    {{ form.as_p }}
    <button type="submit">筛选</button>
</form>

5. 配合分页使用

如果你的商品数据很多,记得加上分页功能,Django的Paginator可以轻松实现,而且筛选排序后的分页也完全兼容,只需要在视图里把products换成分页后的对象就行。


内容的提问来源于stack exchange,提问作者Dennis Gathagu

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.15 04:50:15