0

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

视图.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,})

索引.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>

边栏.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,我如何通过 View 引导它?我想要一个解决方案,它允许我访问从简单的名称列表到输入 D3 图表的相对较大的数据集的任何内容。

解决方案

这就是我最终使用的:

索引.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>

_sidebarSelectorSidebar 的 URL在哪里:

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

2 回答 2

1

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

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

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

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

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

于 2019-08-06T15:13:00.257 回答
0

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

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

  1. 如果需要添加到侧边栏的内容相当有限,请创建一个模板上下文处理器,将其添加到设置(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)
              }
            }
          })
    })
    
于 2019-08-06T15:28:44.597 回答