【问题标题】:Django Nested ViewsDjango 嵌套视图
【发布时间】:2019-12-14 04:12:52
【问题描述】:

我正在开发一个内部应用程序,我希望能够嵌套我的视图以保持一切都井井有条。我计划通过将页面的不同部分保存在自己的 HTML 文件中并使用自己的视图(单独的侧边栏和导航栏、单独的图表等)来做到这一点。

views.py

from django.shortcuts import render
from django.views.generic import TemplateView
import Recall.data_logger.models as DLM


class ReportHome(TemplateView):
    template_name = 'data_logger/index.html'

class SelectorSidebar(TemplateView):
    template_name = 'data_logger/sidebar.html'

    def get(self, request, *args, **kwargs):        
        companies = DLM.Company.objects.order_by('company_name').all()

        return render(request, self.template_name, {'companies':companies,})

index.html

<html>
    <head></head>
    <body data-gr-c-s-loaded="true">
        {% include 'data_logger/navbar.html' %}

        <div class="container-fluid">
            <div class="row">
                {% include 'data_logger/sidebar.html' %} <!-- This is the part I need help with-->
            </div>
        </div>
    </body>
</html>

sidebar.html

<div class="col-sm-3 col-md-1 sidebar">
    <ul class="nav nav-sidebar">
        {% for company in companies %}
            <li><a href="#">{{ company.company_name }}</a></li>
        {% endfor %}
    </ul>
</div>

我知道仅使用{% include 'data_logger/sidebar.html' %} 只是加载HTML 并绕过SelectorSidebar,我如何通过视图引导它? 我想要一个解决方案,它允许我访问从简单的名称列表到输入 D3 图表的相对较大的数据集的任何内容。

解决方案

这是我最终使用的:

index.html

<html>
    <head>
        <script src="https://ajax.googleapis.com/ajax/libs/jquery/3.4.1/jquery.min.js"
                integrity="sha384-vk5WoKIaW/vJyUAd9n/wmopsmNhiy+L2Z+SBxGYnUkunIxVxAv/UtMOhba/xskxh"
                crossorigin="anonymous"></script>
        <script>            
            $.get("_sidebar", function(data, status){
                $("#_sidebar").html(data);
            });
        </script>
    </head>
    <body data-gr-c-s-loaded="true">
        {% include 'data_logger/navbar.html' %}

        <div class="container-fluid">
            <div class="row" id="_sidebar"></div>
        </div>
    </body>
</html>

_sidebar 是 SelectorSidebar 的 URL:

urlpatterns = [
    path('', v.ReportHome.as_view(), name='ReportHome'),
    path('_sidebar', v.SelectorSidebar.as_view(), name='SelectorSidebar'),
]

【问题讨论】:

    标签: html django python-3.x django-2.2


    【解决方案1】:

    我认为您对 Django 模板和视图如何协同工作有些混淆。

    简单来说,Django 模板定义了构成页面的 HTML 代码。您可以使您的模板非常模块化和有条理;为此,您可以使用include 模板标签,也可以使用template inheritance,这是一种非常强大的“模块化”模板方式。

    Django 视图基本上是一个接收 HTTP 请求并构建 HTTP 响应的函数(或者你们中的一个类正在使用基于类的视图)。 拥有“嵌套”视图没有多大意义,因为通常您只有一个 HTTP 请求,而您只想使用显示页面所需的 HTML 构建一个响应。

    所以我认为你可以愉快地使用 Django 模板将构成页面的所有模块(标题、侧边栏等)放在一起,但每个页面都应该对应一个 Django 视图。

    另一种方法可以使用 AJAX 和 Javascript 发出不同的 HTTP 请求并在客户端构建页面,但我认为这不是您在这里考虑的方法。

    【讨论】:

      【解决方案2】:

      正如@baxeico 回答的那样,您不能有多个视图来服务一个页面,因为一个 HTTP 请求就是一个视图。

      如果您的内容需要出现在很多页面上,例如侧边栏,并且该内容还需要一些上下文信息来呈现(例如要从数据库中获取的 companies 列表),您有两种选择:

      1. 如果需要添加到侧边栏的内容相当有限,请创建一个模板context processor,将其添加到设置中的上下文处理器列表中(TEMPLATES 设置)。

        def sidebar_context(request):
            return {'companies': DLM.Company.objects.order_by('company_name').all()}
        

        在您的设置中,您可以在列表顶部添加 'myapp.custom_contexts.sidebar_context' 之类的内容。

        现在,每个模板都可以访问上下文变量companies,包括您的侧边栏模板。

      2. 如果边栏中显示的内容更动态或更复杂,您应该考虑使用 AJAX 从浏览器中获取数据。您将创建一个返回 JSON 而不是 HTML 的视图,并在侧边栏模板中添加 javascript 以获取数据并填充侧边栏。

        视图与您当前的视图一样简单:

        def sidebar(request):
            return JsonResponse({'companies': Company.objects.all().values('name', 'id')})
        

        这将返回包含每个公司的名称和 ID 的字典列表。在成功响应的 AJAX 处理程序(接收data)中,您可以循环访问data 并访问data[i].namedata[i].id,您可以使用它们来填充您的列表。

        我不会发布完整的 javascript(请搜索 jQuery、ajax 和 django),但这里有一些想法,假设是 jQuery:

        $(window).on('load', function() {
              $.ajax({
                url: "{% url 'sidebar' %}",  // assuming this is inside a template, if not {% url %} won't work and you'll have to get it in a different way
                success: function(data) {
                  if (data.length > 0) {
                    for (var i=0; i<data.length; i++) {
                        var elem = $("<li>" + data[i].name + "</li>")
                        $("#companies").append(elem)
                  }
                }
              })
        })
        

      【讨论】:

      • 您能详细说明一下 JS 的样子吗?通过 AJAX 发出多个请求有什么缺点吗?我想要一个允许我访问从名称列表到输入 D3 图表的数据的任何内容的解决方案。
      • 许多现代网站基本上都是由一堆 AJAX 请求填充的基本 HTML 页面。 (反应,角度等......以这种方式工作)。缺点是您的用户必须在他们的浏览器中启用 javascript(现在通常可以),并且您需要 javascript 编码技能,有更多可能出现错误的地方,并增加了测试网站的复杂性。好处是可以更好地分离小型、可重复使用的组件。
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2017-04-10
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2012-03-28
      • 1970-01-01
      相关资源
      最近更新 更多