Reputation: 539
I have a Django project with multiple apps that I need to combine and render as a single page. I have the following sections of code:
One of the views I'm trying to aggregate with other views:
class ResourceList(generic.View):
model = Submissions
template_name = 'url_list.html'
def get(self, request, *args, **kwargs):
resources = Submissions.objects.all()
return render_to_string(self.template_name, {'object_list': resources})
The view I'm trying to use to aggregate my apps:
class Index(View):
def get(self, request, *args, **kwars):
renderable = {
'content': ResourceList(),
'login': LoginView() # I don't care about the LoginView at the moment.
}
return render(request, 'index.html', renderable)
url_list.html
{% extends "base.html" %} <!--I've removed this, it did nothing -->
{% block content }
{{ object.url}}
<ul>
{% for resource in object_list %}
<li> {{resource.url}} {{ resource.id }} {{ resource.rating }}</li>
{% endfor %}
</ul>
{% endblock %}
index.html
<head>
<title>HI</title>
</head>
<body>
{% block login %} login {% endblock %} {% block content %} content {% endblock %}
</body>
</html>
The problem is that it just renders "login content" when I go to the test url I've got set up for the page. If I change render_to_string
to render_to_response
and go to the url I have set up to render just that view everything works perfectly. What's going on here?
Things I've tried:
request
to my object instance in renderable
, I get a __init__ expects 1 argument, got 2
error__init__
on ResourceList to accept a request
argument. It just renders the placeholder content.Upvotes: 0
Views: 1722
Reputation: 13552
You cannot do this like that. Views are glorified functions.
They have a single entry point (dispatch()
) that is invoked by Django internals, and invokes the correct method on itself, depending on the HTTP method (here, get()
).
Casting the view to a string will just display its name, not call it.
If you want to aggregate the behaviors of multiple view, you have several options.
For instance:
from django.views.generic.base import ContextMixin
class ResourceListMixin(ContextMixin):
def get_resource_list(self):
# we put it in a separate method to allow easy overriding
return Submissions.objects.all()
def get_context_data(self, **kwargs):
kwargs['resources'] = self.get_resource_list()
return super(ResourceListMixin, self).get_context_data(**kwargs)
Now you can mix that into any view, and it will automagically know about{{ resources }}
. For instance:
from django.views.generic.base import TemplateView
class IndexView(ResourceListMixin, TemplateView):
template_name = 'index.html'
# nothing else here, we leverage the power of Django's
# TemplateView - it will do everything by itself
Then the IndexView
view will render the index.html
template, and it will be able to do {% for resource in resources %}
.
Upvotes: 1