【问题标题】:Include class based ListView as a template snippet in a TemplateView将基于类的 ListView 作为模板片段包含在 TemplateView 中
【发布时间】:2019-12-01 15:18:52
【问题描述】:

我想要以下:

一个模板视图(实际上是我的登录页面),其中包含许多项目,包括一个列表视图。

现在,当我将它映射到它自己的 url 时,我有一个列表视图:

app/views.py

class MymodelListView(ListView):
    model = Mymodel
    context_object_name = "mymodel_list"

app/urls.py

app_name = "myapp"
urlpatterns = [
 ...
    path("mlist/", MymodelListView.as_view(), name="mlist"),
 ...
]

app/../mymodel_list.html

{% extends 'base.html' %}
{% block content %}
<ul>
    {% for adventure in adventure_list %}
    <li>
        <a href="{{ adventure.get_absolute_url }}">{{ adventure.title }}</a>
    </li>
    {% endfor %}
</ul>
{% endblock content %}

现在这按预期工作,并在“mlist”链接中显示来自 Mymodel 的所有记录。

但是,我想将它嵌入到我的 index.html 模板视图中。我的想法是使用 sn-p 并将其放在 index.html 中

{% include 'myapp/_mymodel_list.html' with mymodel_list=mymodel_list %}

(不确定是否需要“with”部分,但似乎我应该需要将列表从主模板传递到 sn-p。由于更基本,目前无论如何都不起作用问题)。

那么我的主页视图设置如下:

class HomePageView(TemplateView):
    template_name = "index.html"

    def get_context_data(self, *args, **kwargs):
        context = super(HomePageView, self).get_context_data(*args, **kwargs)
        context["adventure_list"] = MymodelListView.get_context_data()
        print(context)
        return context

但这会崩溃:

Exception Type: TypeError at /
Exception Value: super(type, obj): obj must be an instance or subtype of type

如果我将 self 传递给 MymodelListView.get_context_data(self),也是如此。

现在据我所见,Mymodel 的 get 上下文很混乱,因为它正在传递一个 HomePage 上下文,而且有点错误。

我正在尝试做的事情是完全错误的吗?这就是为什么我无法用我的(通常相当可靠的)google-fu 找到任何有用的提示吗?如果是这样,我应该采取什么方法?

我想在其他页面中重复使用 Mymodel 列表视图(尽管可能会更改过滤条件),因此我尝试以 DRY 方式这样做。

【问题讨论】:

    标签: django-templates django-views python-3.7 django-class-based-views django-2.2


    【解决方案1】:

    您看到的问题是您尝试使用HomePageView 的实例调用MymodelListView 的方法。由于HomePageView 不是从MymodelListView 继承的,Python 不能这样做并且会抛出错误。你有几种方法可以解决这个问题。

    myapp/views.py

    # The first approach is to use Django's included mixin to get the
    # queryset and include it in the context. This is a bit redundant and
    # won't include any logic used in your ListView.
    
    from django.views.generic.list import MultipleObjectMixin
    
    
    class HomePageView(MultipleObjectMixin, TemplateView):
        context_object_name = 'adventure_list'
        model = Mymodel
        template_name = 'index.html'
    
    
    # Your second option is to manually include the queryset. Again, this
    # won't include any login from the ListView.
    
    class HomePageView(TemplateView):
        template_name = 'index.html'
    
        def get_context_data(self, **kwargs):
            kwargs.setdefault('adventure_list', Mymodel.objects.all())
            return super().get_context_data(**kwargs)
    
    
    # This is the option that I would suggest. Inherit from the ListView
    # that you've already written and give it its own template and context
    # name. I'm pretty sure this should do exactly what you want.
    
    class HomePageView(MymodelListView):
        context_object_name = 'adventure_list'
        template_name = 'index.html'
    

    我预见到的另一个问题是您正在尝试include 整个 HTML 文件。我怀疑这对你有用。您最好将您的列表放在一个专门包含的文件中,然后在两个地方都使用它。唯一需要复制的是include 标签。

    模板/index.html

    ...
    <!-- If the context name doesn't change you don't need to assign it and
    Django will render the included file correctly. -->
    {% include 'myapp/include_list.html' %}
    ...
    

    模板/myapp/mymodel_list.html

    {% extends 'base.html' %}
    
    {% block content %}
      {% include 'myapp/include_list.html' with adventure_list=mymodel_list %}
    {% endblock %}
    

    模板/myapp/include_list.html

    <ul>
      {% for adventure in adventure_list %}
        <li><a href="{{ adventure.get_absolute_url }}">{{ adventure.title }}</a></li>
      {% endfor %}
    </ul>
    

    【讨论】:

    • 非常感谢您非常彻底的回复和多项建议:)
    猜你喜欢
    • 2013-04-10
    • 1970-01-01
    • 1970-01-01
    • 2023-03-17
    • 1970-01-01
    • 1970-01-01
    • 2012-07-06
    • 2023-04-01
    • 2012-02-09
    相关资源
    最近更新 更多