将基于 class 的 ListView 作为模板片段包含在 TemplateView 中
Include class based ListView as a template snippet in a TemplateView
我想要以下内容:
一个模板视图(实际上是我的登录页面),其中包含许多项目,包括一个列表视图。
现在,我有一个列表视图,当我将它映射到它自己的列表视图时可以使用 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"),
...
]
应用/../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" link.
处显示来自 Mymodel 的所有记录
不过,我想将它嵌入到我的 index.html TemplateView 中。我的想法是使用一个片段并将其放入 index.html
{% include 'myapp/_mymodel_list.html' with mymodel_list=mymodel_list %}
(不确定 "with" 部分是否是必需的,但似乎我应该需要将列表从主模板传递到代码段。目前无论如何都不起作用,因为更基本的问题)。
然后我的主主页视图设置如下:
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 context 很混乱,因为它被传递给了 HomePage context,而且有点不对劲。
我想做的是完全错误的吗?这就是为什么我在我的(通常相当可靠的)google-fu 中找不到任何有用的提示吗?如果是这样,我应该采取什么方法呢?
我想在其他页面中重新使用 Mymodel 列表视图(尽管可能会更改过滤条件),因此我尝试以 DRY 方式这样做。
您遇到的问题是您试图用 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
标签。
templates/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' %}
...
templates/myapp/mymodel_list.html
{% extends 'base.html' %}
{% block content %}
{% include 'myapp/include_list.html' with adventure_list=mymodel_list %}
{% endblock %}
templates/myapp/include_list.html
<ul>
{% for adventure in adventure_list %}
<li><a href="{{ adventure.get_absolute_url }}">{{ adventure.title }}</a></li>
{% endfor %}
</ul>
我想要以下内容:
一个模板视图(实际上是我的登录页面),其中包含许多项目,包括一个列表视图。
现在,我有一个列表视图,当我将它映射到它自己的列表视图时可以使用 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"),
...
]
应用/../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" link.
处显示来自 Mymodel 的所有记录不过,我想将它嵌入到我的 index.html TemplateView 中。我的想法是使用一个片段并将其放入 index.html
{% include 'myapp/_mymodel_list.html' with mymodel_list=mymodel_list %}
(不确定 "with" 部分是否是必需的,但似乎我应该需要将列表从主模板传递到代码段。目前无论如何都不起作用,因为更基本的问题)。
然后我的主主页视图设置如下:
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 context 很混乱,因为它被传递给了 HomePage context,而且有点不对劲。
我想做的是完全错误的吗?这就是为什么我在我的(通常相当可靠的)google-fu 中找不到任何有用的提示吗?如果是这样,我应该采取什么方法呢?
我想在其他页面中重新使用 Mymodel 列表视图(尽管可能会更改过滤条件),因此我尝试以 DRY 方式这样做。
您遇到的问题是您试图用 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
标签。
templates/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' %}
...
templates/myapp/mymodel_list.html
{% extends 'base.html' %}
{% block content %}
{% include 'myapp/include_list.html' with adventure_list=mymodel_list %}
{% endblock %}
templates/myapp/include_list.html
<ul>
{% for adventure in adventure_list %}
<li><a href="{{ adventure.get_absolute_url }}">{{ adventure.title }}</a></li>
{% endfor %}
</ul>