Django嵌套视图 [英] Django Nested Views

查看:135
本文介绍了Django嵌套视图的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在开发一个内部应用程序,我希望能够嵌套我的视图以使所有内容保持井井有条.我计划通过将页面的不同部分保留在自己的HTML文件中并使用自己的视图(单独的侧边栏和导航栏,单独的图表等)来实现此目的.

I'm developing an internal application and I would like to be able to nest my views to keep everything nice and organized. I plan on doing this by keeping different parts of the page in their own HTML files with their own Views (separate sidebar and navbar, separate charts, etc).

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

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

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图表的相对较大的数据集.

I understand that by just using {% include 'data_logger/sidebar.html' %} it's just loading the HTML and bypassing SelectorSidebar, how do I direct it through the View? I'd like a solution that allows me to access anything from a simple list of names to relitively large datasets being fed into a D3 chart.

这是我最终使用的:

index.html

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:

Where _sidebar is the URL to SelectorSidebar:

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

推荐答案

@baxeico回答说,您不能有多个视图来服务页面,因为一个HTTP请求就是一个视图.

As @baxeico answered, you can't have multiple views to serve a page, because one HTTP request is one view.

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

If you have content that needs to appear on a lot of pages, like your sidebar, and that content also requires some context information to render (like a list of companies to fetch from the db), you have two options:

  1. 如果添加到侧边栏所需的内容相当有限,请创建模板上下文处理器,您可以在设置(TEMPLATES设置)中将其添加到上下文处理器列表中.

  1. If the stuff required to add to the sidebar is fairly limited, create a template context processor that you add to the list of context processors in your settings (TEMPLATES setting).

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

,然后在设置中,在列表顶部添加类似'myapp.custom_contexts.sidebar_context'的内容.

and in your settings, you'd add something like 'myapp.custom_contexts.sidebar_context' at the top of the list.

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

Now, every single template has access to the context variable companies, including your sidebar template.

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

If the stuff shown in the sidebar is more dynamic, or more complex, you should consider fetching the data from within the browser using AJAX. You would create a view that returns JSON instead of HTML and in your sidebar template add javascript to fetch the data and populate the sidebar.

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

The view is as simple as your current one:

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

,它将返回包含每个公司名称和ID的字典列表.然后,在成功响应的AJAX处理程序中(接收到data),您可以遍历data并访问data[i].namedata[i].id,可用于填充列表.

which will return a list of dicts containing name and id of each company. In your AJAX handler for the successful response (which receives the data), you can then loop through data and access data[i].name and data[i].id which you can use to populate your list.

我不愿意发布完整的javascript(请搜索jQuery,ajax和django),但是假设使用jQuery,以下是给您的一个想法:

I won't go as far as posting the full javascript (please search for jQuery, ajax and django) but here's a bit to give you an idea, assuming 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)
          }
        }
      })
})

这篇关于Django嵌套视图的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆