- https://blog.csdn.net/weixin_45905671/article/details/115052054

{
"1":{ // 数字编号表示'组号',即对'一级目录'进行分组
"channels":[ // 一级目录
{"id":1, "name":"手机", "url":"http://shouji.jd.com/"},
{"id":2, "name":"相机", "url":"http://www.baidu.cn/"}
],
"sub_cats":[
{
"id":38,
"name":"手机通讯", // 二级目录
"sub_cats":[
{"id":115, "name":"手机"}, // 三级目录
{"id":116, "name":"游戏手机"}
]
},
{
"id":39,
"name":"手机配件", // 二级目录
"sub_cats":[
{"id":119, "name":"手机壳"},// 三级目录
{"id":120, "name":"贴膜"}
]
}
]
},
"2":{
"channels":[],
"sub_cats":[]
}
}
### models.py
class GoodsCategory(BaseModel):
"""
商品类别(分组)
"""
name = models.CharField(max_length=10, verbose_name='名称')
parent = models.ForeignKey('self', null=True, blank=True, on_delete=models.CASCADE, verbose_name='父类别')
class Meta:
db_table = 'tb_goods_category'
verbose_name = '商品类别'
verbose_name_plural = verbose_name
def __str__(self):
return self.name
class GoodsChannel(BaseModel):
"""
商品频道
"""
group_id = models.IntegerField(verbose_name='组号')
category = models.ForeignKey(GoodsCategory, on_delete=models.CASCADE, verbose_name='顶级商品类别')
url = models.CharField(max_length=50, verbose_name='频道页面链接')
sequence = models.IntegerField(verbose_name='组内顺序')
class Meta:
db_table = 'tb_goods_channel'
verbose_name = '商品频道'
verbose_name_plural = verbose_name
def __str__(self):
return self.category.name
视图逻辑如下: 要查询数据库,把数据手动拼接成上述结构返回给前端
### views
from django.shortcuts import render
from django.views import View
from goods.models import GoodsCategory, GoodsChannel
from collections import OrderedDict
class IndexView(View):
"""首页广告"""
def get(self, request):
"""提供首页页面"""
# 查询并展示商品分类
# categories = {} # 优化 OrderedDict 由无序变成有序
categories = OrderedDict()
# 查询所有的商品频道
channels = GoodsChannel.objects.order_by('group_id', 'sequence')
for channel in channels:
# 37个频道 11个组
group_id = channel.group_id
# print(group_id)
if group_id not in categories:
categories[group_id] = {'channels': [], 'sub_cats': []}
# print(categories)
cat1 = channel.category
categories[group_id]['channels'].append(
{
"id": cat1.id,
"name": cat1.name,
"url": channel.url
}
)
# print(categories) # 打印结果一级分类完成
# 查询二级和三级类别
# 查询二级 parent_id = cat1.id
# for cat2 in cat1.subs.all(): 此行简写代码可替换下面一行代码 models.py中定义了related_name=subs
for cat2 in GoodsCategory.objects.filter(parent_id=cat1.id).all():
cat2.sub_cats = []
categories[group_id]["sub_cats"].append(
{
"id": cat2.id,
"name": cat2.name,
"sub_cats": cat2.sub_cats
}
)
# for cat3 in cat2.subs.all():
for cat3 in GoodsCategory.objects.filter(parent_id=cat2.id).all():
cat2.sub_cats.append(
{
"id": cat3.id,
"name": cat3.name,
}
)
print(categories)
'''
{
"1":{
"channels":[
{"id":1, "name":"手机", "url":"http://shouji.jd.com/"},
{"id":2, "name":"相机", "url":"http://www.baidu.cn/"}
],
"sub_cats":[
{
"id":38,
"name":"手机通讯",
"sub_cats":[
{"id":115, "name":"手机"},
{"id":116, "name":"游戏手机"}
]
},
{
"id":39,
"name":"手机配件",
"sub_cats":[
{"id":119, "name":"手机壳"},
{"id":120, "name":"贴膜"}
]
}
]
},
'''
context = {
"categories": categories
}
return render(request, 'index.html', context=context)
<ul class="sub_menu">
{% for group in categories.values %}
<li>
<div class="level1">
{% for channel in group.channels %}
<a href="{{ channel.url }}">{{ channel.name }}</a>
{% endfor %}
</div>
<div class="level2">
{% for cat2 in group.sub_cats %}
<div class="list_group">
<div class="group_name fl">{{ cat2.name }} ></div>
<div class="group_detail fl">
{% for cat3 in cat2.sub_cats %}
<a href="/list/{{ cat3.id }}/1/">{{ cat3.name }}</a>
{% endfor %}
</div>
</div>
{% endfor %}
</div>
</li>
{% endfor %}
</ul>