【问题标题】:Django - Rendering Inclusion Tag from a ViewDjango - 从视图中渲染包含标记
【发布时间】:2010-08-18 15:51:53
【问题描述】:

所以我想知道您是否可以直接从视图中返回包含标记。

该页面是带有项目列表的普通页面。使用包含标签呈现项目列表。如果对视图发出 ajax 请求,我只想返回包含标记将返回的内容,以便我可以通过 javascript 将其附加到页面上。这样的事情可能吗?还是我应该更好地构建这个?

【问题讨论】:

    标签: django django-templates


    【解决方案1】:

    这听起来像是 render_to_string 或 render_to_response 快捷方式的工作:
    https://docs.djangoproject.com/en/dev/ref/templates/api/#the-render-to-string-shortcut
    https://docs.djangoproject.com/en/dev/topics/http/shortcuts/#django.shortcuts.render_to_response

    我们仍然可以使用包含标记从我们的 args 生成模板上下文字典(正如 @BobStein-VisiBone 在 cmets 中有用地指出的那样)

    from django.template.loader import render_to_string
    from django.shortcuts import render_to_response
    
    from .templatetags import my_inclusion_tag
    
    
    rendered = render_to_string('my_include.html', my_inclusion_tag(foo='bar'))
    
    #or
    
    def my_view(request):
        if request.is_ajax():
            return render_to_response('my_include.html',
                          my_inclusion_tag(foo='bar'),
                          context_instance=RequestContext(request))
    

    【讨论】:

    • 这样做意味着你必须重复要在视图中渲染的模板的名称,这违反了 DRY 原则
    • @Craig 得到 DRY 是微不足道的,只需将模板的名称存储在一个变量中,并在您的视图和定义包含标签的位置使用 var
    • 并不是 O.P. 给出了任何开始的例子,但你的例子中缺少的是包含标签功能的任何提及。事实证明,即使它被修饰了,仍然可以直接调用它来输出一个字典,为 render_to_string() 准备好。我建议将代码中的两个字典都替换为:my_inclusion_tag_function(arguments) 并在顶部添加 from templatetags.my_file include my_inclusion_tag_function 或其他内容。
    【解决方案2】:

    快速而肮脏的方法可能是拥有一个视图,它呈现一个仅包含您的模板标签的模板。

    【讨论】:

    • 是的,这种方式在代码中似乎是多余的,希望得到一些不涉及额外步骤的东西。
    • 然后将序列化模型公开为 json ,查看code.google.com/p/django-rest-interface 以开始,或者推出自己的应用程序,使用不同的 URL 命名空间而不是在现有视图中分支!
    【解决方案3】:

    我今天尝试做同样的事情,最后写了一个辅助函数来渲染模板标签:

    def render_templatetag(request, tag_string, tag_file, dictionary=None):
        dictionary = dictionary or {}
        context_instance = RequestContext(request)
        context_instance.update(dictionary)
        t = Template("{%% load %s %%}{%% %s %%}" % (tag_file, tag_string))
        return t.render(context_instance)
    

    tag_string 是对模板标签的调用,因为它会出现在普通模板中,而 tag_file 是您需要为模板标签加载的文件。

    【讨论】:

    • 这毫无意义,标签渲染应该在模板中完成,而不是在视图代码中。您可以使用包含标签来避免重复模板代码。
    • 这样做意味着您不必重复要在视图中呈现的模板的名称
    • @Craig 是的,但是你必须在你的视图中重复模板中使用的标签字符串,它不再是 DRY
    【解决方案4】:

    这当然是可能的。视图可以呈现包含标签可以呈现的任何模板。这种方法的优点是您可以充分利用 Django 模板的全部优势。

    另一方面,AJAX 响应通常不像 XML/JSON 那样包含 HTML。如果您使用 Django 的模板功能,则最好返回 HTML。如果没有,XML/JSON 可能更有意义。只是我的两分钱。

    【讨论】:

    • 我总是遇到返回 xml/json 然后让 javascript 将数据呈现为 html 的问题。这不是违反 DRY 原则吗,因为现在我们在 django 模板和 javascript 中复制了代码。
    • 你提到它可以做到,但你没有包括一个例子。你能告诉我怎么做或有它的页面吗?
    【解决方案5】:

    使用 inclusion tag with configurable template decorator provided by Gonz 代替默认的 Django 包含标签,您可以在视图中编写帮助程序:

    from django.template.loader import render_to_string
    from home.templatetags.objectwidgets import object_widget
    
    def _object_widget(request, obj):
        template, context = object_widget(RequestContext(request), obj)
        return render_to_string(template, context)
    

    它是 DRY 并且适用于 Django 1.3(我尚未使用 Django 1.4 对其进行测试)。

    我使用这种技术通过 JSON/AJAX 调用返回以 HTML 呈现的搜索结果(我想出的没有更好的方法)。

    【讨论】:

      【解决方案6】:

      这是可能的,但可能有点老套、复杂或复杂。

      我的建议是构建它,以便您在 utils.py 函数中拥有渲染部分,并在 simple_tag 中使用它,而不是在 contains_tag 中使用它。这样您就可以在视图中轻松使用相同的 utils 渲染功能。

      在我的(非常简化的)虚构示例中,我列出了用户和返回更多用户的“加载更多”按钮。

      account/utils.py

      from django.template.loader import render_to_string
      
      
      def render_users(users):
          return render_to_string("account/user_list_items.html", {"users": users})
      

      account/templatetags/account_tags.py

      from django import template
      
      from ..utils import render_users
      
      register = template.Library()
      
      
      @register.simple_tag
      def list_users(users):
          return render_users(users)
      

      account/views.py

      from django.http import HttpResponse
      
      from .models import User
      from .utils import render_users
      
      
      def load_more_users(request):
          limit = request.GET["limit"]
          offset = request.GET["offset"]
          users = User.objects.all()[offset:offset + limit]
          return HttpResponse(render_users(users))
      

      简单胜于复杂。

      【讨论】:

        猜你喜欢
        • 2016-07-27
        • 1970-01-01
        • 2020-04-02
        • 2015-02-04
        • 2018-02-12
        • 1970-01-01
        • 2018-12-13
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多