Django菜单实现求助:输出菜单列表及匹配ID的子菜单
Django 层级菜单实现步骤
1. 定义菜单模型
在你的app下的models.py里创建菜单模型,通过自关联外键实现父子菜单的层级关系:
from django.db import models class Menu(models.Model): name = models.CharField(max_length=50, verbose_name="菜单名称") # 父菜单关联自身,null/blank允许该菜单为顶级菜单 parent = models.ForeignKey('self', on_delete=models.CASCADE, null=True, blank=True, related_name='submenus', verbose_name="父菜单") menu_id = models.CharField(max_length=50, unique=True, verbose_name="匹配用ID") # 对应你需要的'catr' def __str__(self): return self.name
写完模型后执行迁移命令:
python manage.py makemigrations python manage.py migrate
然后到Django后台添加数据:先创建顶级菜单name='catr'、menu_id='catr';再创建子菜单name='subcat',父菜单选择刚才的catr即可。
2. 编写视图逻辑
在views.py中查询菜单数据,并获取当前需要匹配的菜单ID(以下提供两种常见获取方式):
from django.shortcuts import render from .models import Menu # 方式1:从URL路径参数获取匹配ID def menu_view(request, menu_id=''): # 预加载子菜单,减少数据库查询次数 parent_menus = Menu.objects.filter(parent__isnull=True).prefetch_related('submenus') return render(request, 'menu.html', { 'parent_menus': parent_menus, 'current_menu_id': menu_id }) # 方式2:从GET参数获取匹配ID(比如访问时带?menu_id=catr) # def menu_view(request): # current_menu_id = request.GET.get('menu_id', '') # parent_menus = Menu.objects.filter(parent__isnull=True).prefetch_related('submenus') # return render(request, 'menu.html', {'parent_menus': parent_menus, 'current_menu_id': current_menu_id})
如果用路径参数的方式,需要在urls.py中配置路由:
from django.urls import path from . import views urlpatterns = [ path('menu/<str:menu_id>/', views.menu_view, name='menu'), # 可选:添加默认路径,不带参数时展示所有顶级菜单 path('menu/', views.menu_view, name='menu_default'), ]
3. 模板渲染菜单
在模板文件menu.html中循环渲染菜单,当菜单ID与当前匹配ID一致时,展开对应的子菜单:
<ul class="menu-list"> {% for parent in parent_menus %} <li class="menu-item"> {{ parent.name }} <!-- 匹配到目标菜单ID且存在子菜单时,展开子菜单 --> {% if parent.menu_id == current_menu_id and parent.submenus.exists %} <ul class="submenu-list"> {% for sub in parent.submenus.all %} <li class="submenu-item">{{ sub.name }}</li> {% endfor %} </ul> {% endif %} </li> {% endfor %} </ul>
测试验证
启动Django服务后,访问http://localhost:8000/menu/catr/,就能看到catr菜单下展开subcat子菜单;访问http://localhost:8000/menu/则只显示所有顶级菜单。
内容的提问来源于stack exchange,提问作者Lightcart
相关产品推荐
相关产品推荐

