组合搜索筛选标签

我们在平时的网页上肯定看过用不同条件进行筛选的标签页面,例如淘宝购物,什么品牌的什么商品,在django中,这是一个比较基本的技能:

1.首先我们现在models中创建我们进行筛选的条件,每个条件都是一个单独的数据表,并进行对条件的关联,例如买东西来说来说,首先有一个大类,方向:如衣服,裤子,鞋子等,其次在大方向下有各种品牌:nike,adidas,puma等,在有价位,最后是商品信息(还有更多条件,根据项目需求自定制,这里只列举这么多)

models.py
class Direction(models.Model):
    name = models.CharField(max_length=32,verbose_name='方向')
    #方向与品牌是多对多关系,
    classification = models.ManyToManyField('Classification')
    def __str__(self):
        return self.name
    class Meta:
        verbose_name_plural='方向'
class Classification(models.Model):
    name = models.CharField(max_length=32,verbose_name='品牌分类')
    def __str__(self):
        return self.name
    class Meta:
        verbose_name_plural='品牌'

class Level(models.Model):
    name = models.CharField(max_length=32 , verbose_name='价位')
    def __str__(self):
        return self.name
    class Meta:
        verbose_name_plural='价位'

class Goods(models.Model):
    name = models.CharField(max_length=32,verbose_name='商品名称')
    #商品根据品牌和价位来筛选
    classification = models.ForeignKey('Classification',on_delete=models.CASCADE)
    level = models.ForeignKey('Level',on_delete=models.CASCADE)
    up_date = models.DateTimeField()
    def __str__(self):
        return self.name
    class Meta:
        verbose_name_plural='商品'
#所有的verbose都是在admin中显示中文

2.然后我们就在url中设置路径,不过这里的路径需要配合我们的html进行配置,

#这里可以引入re_path用正则表达式,也可以不用,这是django2.0的新规则
urlpatterns = [
re_path('goods-(?P<direction_id>(\d+))-(?P<classification_id>(\d+))-(?P<level_id>(\d+))/',views.goods),
#根据正则表达式,我们将html中各个东西的id发送给我们的后台,这样就可以针对性操作id
]

3.views的设置和templates中进行配置,首先我们要从数据库中,拿出我们存在的数据,显示在页面中,供用户点击,首先我们要明确,方向是要展示给用户作为第一个选项的,所以必须全部展示出来,而品牌则是根据方向来进行显示,所以,我们要根据分类来展示品牌,不能一股脑的全部展示出来,价位也是我们要全部拿出来展示的,供用户挑选。最后根据筛选的条件展示商品:

views.py

def goods(request,*args,**kwargs):
    #商品搜索条件字典
    condition = {}
    direction_list = Direction.objects.all()
    #classification_lsit要根据方向的值来确定具体的展示
    level_list = Level.objects.all()
    goods_list = Goods.objects.filter(**condition)
    #我们添加筛选条件进字典中,进行搜索
    return render(request,'goods.html',locals())
goods.html
#如果页面id与用户选中的标签id相同,那么我们给这个a标签添加一个特殊样式,这里设置了active类,自定义样式
<body>
<p>筛选</p>
    <div>
        <div class="content">
            {% if kwargs.direction_id == 0 %}
                    <a class="active">全部</a>
            {% else %}
                    <a>全部</a>
            {% endif %}
            {% for row in direction_list %}
                {% if kwargs.direction_id == row.id %}
                    <a class="active">{{ row.name }}</a>
                {% else %}
                    <a>{{ row.name }}</a>
                {% endif %}
            {% endfor %}
        </div>

        <div class="content">
            {% if kwargs.classification_id == 0 %}
                    <a class="active">全部</a>
                {% else %}
                    <a>全部</a>
            {% endif %}
            {% for row in classification_list %}
                {% if kwargs.classification_id == row.id %}
                    <a class="active">{{ row.name }}</a>
                {% else %}
                    <a>{{ row.name }}</a>
                {% endif %}
            {% endfor %}
        </div>
        <div class="content">
            {% if kwargs.level_id == 0 %}
                    <a class="active">全部</a>
                {% else %}
                    <a>全部</a>
            {% endif %}
            {% for row in level_list %}
                {% if kwargs.level_id == row.id %}
                    <a class="active">{{ row.name }}</a>
                {% else %}
                    <a>{{ row.name }}</a>
                {% endif %}
            {% endfor %}
        </div>

    </div>
    <div>
        <p>结果</p>
        {% for row in goods_list %}
            {{ row.name }}
        {% endfor %}
    </div>
</body>

TIPS:代码中有个小问题,我们在对id经行对比是,如果你仅仅按照上述代码,是不会有active样式在你的a标签中的,并不是逻辑出错,而是在if判断中,2个值并不相等,为何不相等呢?因为我们在url中获得的值并不是数字类型而是string类型,而id是int类型,所以我们在views中首先要将kwargs中的各个值转化为int类型才能进行比较。
基本的页面结构就已经出来了,接下来我们就要设置a标签里的href以及在views中的classification_list是如何产生的,condition中的条件到底如何添加。

对方向的id的讨论,如果我们选中全部,即direction_id是0,那么就要显示全部的品牌名称,如果不为0,那就要找到对应direction_id的品牌名称,通过第三张表获得,(还有一个问题,我们选择不同方向时,如果该方向中并没有上一次选中的品牌,我们应当要让品牌标签选中全部,例如:第一次选择上衣,品牌选择nike,第二次选择眼镜,这是我们还没选择品牌,这时候,我们的品牌id任然指向nike,我们应当在第二次选择眼镜时,品牌应该放在全部里面,所以我们要弄一个列表,将当前方向下所有品牌id放在列表中,如果下次品牌的id并不在当前分类的列表中,则让品牌id等于0)。

我们的查询条件condition字典,也应该在刚才讨论direction_id中顺便添加,判断各个id是否为0,判断是否要在字典中添加条件,如果字典为空,那么filter()相当于all()。

href的设置,如果我们点了方向标签,那么,我们的direction_id是在动态改变的,而其他两个不会改变,当选择全部时,direction_id永远等于0,其他2个标签也是这样,只改变一个值而另外2个不随之改变。
所以完整代码:

views.py
def goods(request,*args,**kwargs):
    #视频搜索条件字典
    condition = {}
    #将id变为int
    for k,v in kwargs.items():
        kwargs[k] = int(v)
    direction_list = Direction.objects.all()
    level_list = Level.objects.all()
    if kwargs.get('direction_id') == 0:
        classification_list = Classification.objects.all()
        #判断是否classification_id是否为0,如果不为0,在条件字典中添加id
        if kwargs.get('classification_id') != 0:
            condition['classification_id'] = kwargs.get('classification_id')
    else:
        obj = Direction.objects.filter(id=kwargs.get('direction_id')).first()
        classification_list = obj.classification.all()
        vlist=[]
        #判断classification_list是否为空,如果为空vlist中则不传值
        if classification_list:
            for v in classification_list:
                vlist.append(v.id)
        if kwargs.get('classification_id') in vlist:
            condition['classification_id'] = kwargs.get('classification_id')
        else:
            condition['classification__id__in'] = vlist
            kwargs['classification_id'] = 0
    if kwargs.get('level_id') != 0:
        condition['level_id'] = kwargs.get('level_id')
    goods_list = Goods.objects.filter(**condition)
    return render(request,'goods.html',locals())
goods.html
<body>
<p>筛选</p>
    <div>
        <div class="content">
            {% if kwargs.direction_id == 0 %}
                    <a class="active" href="/video-0-{{ kwargs.classification_id }}-{{ kwargs.level_id }}">全部</a>
                {% else %}
                    <a href="/video-0-{{ kwargs.classification_id }}-{{ kwargs.level_id }}">全部</a>
            {% endif %}
            {% for row in direction_list %}
                {% if kwargs.direction_id == row.id %}
                    <a class="active" href="/video-{{ row.id }}-{{ kwargs.classification_id }}-{{ kwargs.level_id }}">{{ row.name }}</a>
                {% else %}
                    <a href="/video-{{ row.id }}-{{ kwargs.classification_id }}-{{ kwargs.level_id }}">{{ row.name }}</a>
                {% endif %}
            {% endfor %}
        </div>

        <div class="content">
            {% if kwargs.classification_id == 0 %}
                    <a class="active" href="/video-{{ kwargs.direction_id }}-0-{{ kwargs.level_id }}">全部</a>
                {% else %}
                    <a href="/video-{{ kwargs.direction_id }}-0-{{ kwargs.level_id }}">全部</a>
            {% endif %}
            {% for row in classification_list %}
                {% if kwargs.classification_id == row.id %}
                    <a class="active" href="/video-{{ kwargs.direction_id }}-{{ row.id }}-{{ kwargs.level_id }}">{{ row.name }}</a>
                {% else %}
                    <a href="/video-{{ kwargs.direction_id }}-{{ row.id }}-{{ kwargs.level_id }}">{{ row.name }}</a>
                {% endif %}
            {% endfor %}
        </div>
        <div class="content">
            {% if kwargs.level_id == 0 %}
                    <a class="active" href="/video-{{ kwargs.direction_id }}-{{ kwargs.classification_id }}-0">全部</a>
                {% else %}
                    <a href="/video-{{ kwargs.direction_id }}-{{ kwargs.classification_id }}-0">全部</a>
            {% endif %}
            {% for row in level_list %}
                {% if kwargs.level_id == row.id %}
                    <a class="active" href="/video-{{ kwargs.direction_id }}-{{ kwargs.classification_id }}-{{ row.id }}">{{ row.name }}</a>
                {% else %}
                    <a href="/video-{{ kwargs.direction_id }}-{{ kwargs.classification_id }}-{{ row.id }}">{{ row.name }}</a>
                {% endif %}
            {% endfor %}
        </div>

    </div>
    <div>
        <p>结果</p>
        {% for row in goods_list %}
            {{ row.name }}
        {% endfor %}
    </div>
</body>

这样一个组合搜索筛选标签就完成了

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值