我们在平时的网页上肯定看过用不同条件进行筛选的标签页面,例如淘宝购物,什么品牌的什么商品,在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>
这样一个组合搜索筛选标签就完成了