【问题标题】:Is there a way to call two function-based views from views.py from one url? - Django or even by using Class-based view有没有办法从一个 url 从views.py 调用两个基于函数的视图? - Django 甚至使用基于类的视图
【发布时间】:2019-08-09 08:24:55
【问题描述】:

我尝试了两种不同风格的视图:基于函数和基于类。我的views.py 中有两个函数,我不知道如何在同一个url 下调用它们。我已经看到将这两个功能合二为一的建议,但它仍然不起作用。

从基于类的视图中尝试 get() 并用不同的视图调用相同的 url

    path('home/dashboard/', views.get_profile, name='dashboard'),
    path('home/dashboard/', views.get_dept, name='dashboard'),

         def get_dept(request, *args, **kwargs):
            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 = list()
        IT_series_data = list()
        Sales_series_data = list()
        Admin_series_data = list()
        HR_series_data = list()

        for entry in dataset:
            categories.append('%s Department' % entry['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'])

        IT_series = {
            'name': 'IT',
            'data': IT_series_data,
            'color': 'green'
        }

        Sales_series = {
            'name': 'Sales',
            'data': Sales_series_data,
            'color': 'yellow'
        }

        Admin_series = {
            'name': 'Admin',
            'data': Admin_series_data,
            'color': 'red'
        }

        HR_series = {
            'name': 'HR',
            'data': HR_series_data,
            'color': 'blue'
        }

        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': [IT_series, Sales_series, Admin_series, HR_series],
            'colorByPoint': "true",
        }

        dump2 = json.dumps(chart2)

        return render(request, 'accounts/dashboard.html', {'chart2': dump2})


def get_profile(request, *args, **kwargs):
        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))) \

        # categories = list('User')
        is_active_series_data = list()
        not_is_active_series_data = list()

        for entry in dataset:
            # categories.append('User')
            is_active_series_data.append(entry['is_active_count'])
            not_is_active_series_data.append(entry['not_is_active_count'])

        is_active_series = {
            'name': 'Active user',
            'data': is_active_series_data,
            'color': '#23CE3F'
        }

        not_is_active_series = {
            'name': 'Inactive user',
            'data': not_is_active_series_data,
            'color': '#FB3A3A'
        }

        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': [is_active_series, not_is_active_series]
        }

        dump = json.dumps(chart)

        return render(request, 'accounts/dashboard.html', {'chart': dump})

【问题讨论】:

  • 您的意思是您希望用户转到一个 GET URL,然后 Django 呈现两个视图?我不认为这是可能的。 Django 通常在 URL 和“do stuff”函数之间有 1:1 的映射。您可以将 GET 和 POST 的 URL 分开,因此您有一个路由和一个视图用于 GET,一个路由和一个视图用于 POST(具有相同的路由路径)但​​是如果您想在仪表板中显示图表和图表 2,那么您需要通过conext 中的两个图表作为单独的变量,然后您的仪表板视图将显示它们

标签: python html django highcharts


【解决方案1】:

django 无法将两个视图放在一个 url 上。也许您可以将这些功能组合在一个基于类的视图中,实际上它非常简单。例如:

# view
from django.views.generic import TemplateView


class DashboardView(TemplateView):
     template_name = 'accounts/dashboard.html'

     def get_dept(self):
        # rest of the code....
        dump2 = json.dumps(chart2)
        return dump2

    def get_profile(self):
        # rest of the code....
        dump = json.dumps(chart)
        return dump

    def get_context_data(self, *args, **kwargs):
        context = super(ChartView, self).get_context_data(*args, **kwargs)
        context['chart'] = self.get_profile()
        context['chart2'] = self.get_dept()
        return context

# url
path('home/dashboard/', views.DashboardView.as_view(), name='dashboard'),

在模板中,你应该得到{{ chart }} 和{{ chart2 }} 变量中的值。

【讨论】:

  • 什么是 ChartView?
【解决方案2】:

没有。 Django 视图本质上是一个函数,它处理您的request(一个HttpRequest 对象)并返回一个包含您的HTML 页面或JSON 文档或任何预期响应的HttpResponse 对象。所以只能有一个视图函数处理您的请求。

请注意,基于类的视图最终也只是一个函数(.as_view() 将类dispatch 方法作为函数返回)。

当然,在一个函数视图中,您可以调用其他 python 函数来返回产生所需结果所需的任何结果。在您的情况下,您只想生成两个图表以传递给同一个模板 (dashboard.html)。

因此,与其让它们返回`render(request, template, context),不如让它们返回上下文的数据。然后您的一个视图可以将两种上下文合并为一个:

def dashboard_view(request, *args, **kwargs):

    dump1 = get_dept()  # note you don't use request, *args, **kwargs so you don't need to add them as params to get_dept()
    dump2 = get_profile()  # idem
    context = {'chart1': dump1, 'chart2': dump2}
    return render(request, 'dashboard.html', context)

@ruddra 的答案是使用基于类的视图的类似方法。那将是首选的“Django”方式。

【讨论】:

    【解决方案3】:

    如果您想要实现的是在一个视图中从两个函数中获取数据,您应该从一个视图将信息传递给上下文。

    示例:

    class MyView(View):
        def get_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)))
            return dataset
    
    
        def get_dept(request, *args, **kwargs):
            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')
    
           return dataset
    
        def get_context_data(self, **kwargs):
            context = super().get_context_data(**kwargs)
            context['profile'] = self.get_profile()
            context['other_data'] = self.get_depth()
    
    

    然后你可以只调用基于类的视图,上下文将可用

    【讨论】:

      【解决方案4】:

      我如何将数据渲染到模板中

      我想将徽标从任何模板文件更新为 base.html

      在 django 上,我们扩展 base.html 或任何 html 文件

      我们在该块中创建一个块部分将被添加到该块部分 布局/base.html

       <main class="container my-3">
              {% block content %} {% endblock content %}
          </main>
      
      

      任何模板文件

      home.html

      {% block content %}
      
      ... html code 
      {% endfor %}
      
      

      所以我再为徽标创建一个块

      在 base.html 中,我们定义了默认值

      当从扩展模板块值更新基本块时,它被渲染

      基本模板

      
       {% block main_logo %}
                  <a href="/"><img title="Logo" alt=" Logo" src="/static/img/logo.png"></a>
                  {% endblock %}
      

      扩展模板

      {% block main_logo %}
      
                  <a href="/"><img title="Logo" alt=" Logo" src="/static/img/logo-new-one.png"></a>
      {% endblock %}
      

      【讨论】:

        猜你喜欢
        • 2013-02-04
        • 1970-01-01
        • 2014-02-16
        • 1970-01-01
        • 1970-01-01
        • 2013-01-10
        • 1970-01-01
        • 2018-12-11
        • 2021-03-28
        相关资源
        最近更新 更多