Django中如何通过单个URL调用两个基于函数的视图?
解决Django同一URL下展示两个视图图表的问题
我懂你现在的困扰——你想在home/dashboard/这个页面同时展示两个图表,但目前两个视图函数各自生成一个图表的数据,没法在同一个URL里同时生效。核心问题其实是Django的URL规则里,同一个路径只能映射到一个视图,你之前重复设置URL的话,Django只会匹配第一个,第二个视图根本不会被触发。下面给你两种简单可行的解决办法:
方法1:合并两个视图函数的逻辑
最直接的方式就是把两个视图里生成图表的逻辑整合到一个函数中,一次性把两个图表的数据都传给模板。这样同一个URL只需要映射到这个合并后的视图即可。
修改后的视图函数代码:
from django.shortcuts import render from django.db.models import Count, Q import json from .models import Department, Profile def dashboard_view(request, *args, **kwargs): # 处理部门容器统计图表(原get_dept逻辑) dept_dataset = Department.objects.all() \ .values('department') \ .annotate( IT_count=Count('department', filter=Q(department="IT")), Sales_count=Count('department', filter=Q(department="Sales")), Admin_count=Count('department', filter=Q(department="Admin")), HR_count=Count('department', filter=Q(department="HR")) ) \ .order_by('department') categories = [] IT_series_data = [] Sales_series_data = [] Admin_series_data = [] HR_series_data = [] for entry in dept_dataset: categories.append(f'{entry["department"]} Department') IT_series_data.append(entry['IT_count']) Sales_series_data.append(entry['Sales_count']) Admin_series_data.append(entry['Admin_count']) HR_series_data.append(entry['HR_count']) chart2 = { 'chart': { 'type': 'column', 'backgroundColor': '#E3F0E6', 'option3d': { 'enabled': "true", 'alpha': 10, 'beta': 15, 'depth': 50, } }, 'title': {'text': 'Containers per department'}, 'xAxis': {'categories': categories}, 'yAxis': { 'title': {'text': 'No.of containers'}, 'tickInterval': 1 }, 'plotOptions': { 'column': { 'pointPadding': 0.2, 'borderWidth': 0, 'depth': 60, } }, 'series': [ {'name': 'IT', 'data': IT_series_data, 'color': 'green'}, {'name': 'Sales', 'data': Sales_series_data, 'color': 'yellow'}, {'name': 'Admin', 'data': Admin_series_data, 'color': 'red'}, {'name': 'HR', 'data': HR_series_data, 'color': 'blue'} ], 'colorByPoint': "true", } dump2 = json.dumps(chart2) # 处理用户活跃状态统计图表(原get_profile逻辑) profile_dataset = Profile.objects \ .values('is_active') \ .annotate( is_active_count=Count('is_active', filter=Q(is_active=True)), not_is_active_count=Count('is_active', filter=Q(is_active=False)) ) is_active_series_data = [] not_is_active_series_data = [] for entry in profile_dataset: is_active_series_data.append(entry['is_active_count']) not_is_active_series_data.append(entry['not_is_active_count']) chart = { 'chart': { 'type': 'column', 'backgroundColor': '#E3F0E6', 'options3d': { 'enabled': "true", 'alpha': 10, 'beta': 15, 'depth': 50, } }, 'title': {'text': 'Active user on Current Platform'}, 'xAxis': {'categories': ['Active', 'Inactive']}, 'yAxis': { 'title': {'text': 'No.of users'}, 'tickInterval': 1 }, 'plotOptions': { 'column': { 'pointPadding': 0.2, 'borderWidth': 0, 'depth': 60, } }, 'series': [ {'name': 'Active user', 'data': is_active_series_data, 'color': '#23CE3F'}, {'name': 'Inactive user', 'data': not_is_active_series_data, 'color': '#FB3A3A'} ] } dump = json.dumps(chart) # 同时传递两个图表数据到模板 return render(request, 'accounts/dashboard.html', {'chart': dump, 'chart2': dump2})
然后修改URL配置,只保留一条映射:
path('home/dashboard/', views.dashboard_view, name='dashboard'),
方法2:使用基于类的视图(CBV)拆分逻辑
如果想保持代码的模块化,也可以用CBV把两个图表的数据获取逻辑拆分成独立方法,再在get_context_data里统一传递给模板:
from django.views.generic import TemplateView from django.db.models import Count, Q import json from .models import Department, Profile class DashboardView(TemplateView): template_name = 'accounts/dashboard.html' def _get_dept_chart_data(self): # 封装部门图表数据逻辑 dept_dataset = Department.objects.all() \ .values('department') \ .annotate( IT_count=Count('department', filter=Q(department="IT")), Sales_count=Count('department', filter=Q(department="Sales")), Admin_count=Count('department', filter=Q(department="Admin")), HR_count=Count('department', filter=Q(department="HR")) ) \ .order_by('department') categories = [] IT_series_data = [] Sales_series_data = [] Admin_series_data = [] HR_series_data = [] for entry in dept_dataset: categories.append(f'{entry["department"]} Department') IT_series_data.append(entry['IT_count']) Sales_series_data.append(entry['Sales_count']) Admin_series_data.append(entry['Admin_count']) HR_series_data.append(entry['HR_count']) chart2 = { 'chart': { 'type': 'column', 'backgroundColor': '#E3F0E6', 'option3d': { 'enabled': "true", 'alpha': 10, 'beta': 15, 'depth': 50, } }, 'title': {'text': 'Containers per department'}, 'xAxis': {'categories': categories}, 'yAxis': { 'title': {'text': 'No.of containers'}, 'tickInterval': 1 }, 'plotOptions': { 'column': { 'pointPadding': 0.2, 'borderWidth': 0, 'depth': 60, } }, 'series': [ {'name': 'IT', 'data': IT_series_data, 'color': 'green'}, {'name': 'Sales', 'data': Sales_series_data, 'color': 'yellow'}, {'name': 'Admin', 'data': Admin_series_data, 'color': 'red'}, {'name': 'HR', 'data': HR_series_data, 'color': 'blue'} ], 'colorByPoint': "true", } return json.dumps(chart2) def _get_profile_chart_data(self): # 封装用户活跃图表数据逻辑 profile_dataset = Profile.objects \ .values('is_active') \ .annotate( is_active_count=Count('is_active', filter=Q(is_active=True)), not_is_active_count=Count('is_active', filter=Q(is_active=False)) ) is_active_series_data = [] not_is_active_series_data = [] for entry in profile_dataset: is_active_series_data.append(entry['is_active_count']) not_is_active_series_data.append(entry['not_is_active_count']) chart = { 'chart': { 'type': 'column', 'backgroundColor': '#E3F0E6', 'options3d': { 'enabled': "true", 'alpha': 10, 'beta': 15, 'depth': 50, } }, 'title': {'text': 'Active user on Current Platform'}, 'xAxis': {'categories': ['Active', 'Inactive']}, 'yAxis': { 'title': {'text': 'No.of users'}, 'tickInterval': 1 }, 'plotOptions': { 'column': { 'pointPadding': 0.2, 'borderWidth': 0, 'depth': 60, } }, 'series': [ {'name': 'Active user', 'data': is_active_series_data, 'color': '#23CE3F'}, {'name': 'Inactive user', 'data': not_is_active_series_data, 'color': '#FB3A3A'} ] } return json.dumps(chart) def get_context_data(self, **kwargs): context = super().get_context_data(**kwargs) context['chart'] = self._get_profile_chart_data() context['chart2'] = self._get_dept_chart_data() return context
对应的URL配置:
path('home/dashboard/', views.DashboardView.as_view(), name='dashboard'),
最后记得在模板dashboard.html里,分别用{{ chart }}和{{ chart2 }}来初始化两个图表即可。
内容的提问来源于stack exchange,提问作者Django Newbie
相关产品推荐
相关产品推荐

