Loading views into template without Ajax on Django - django

Good evening people. I have this Django question.. I have a view that renders a form with a header information from a master-detail like models. Below this form, I want to load another view that renders a form that fills the detail table and next to it, the list with the detail. I want to load inside the template of the header view, the detail's view but I want to do it without ajax. I was reading the {% include %} tag but, from what I understand, it loads a template, not a view. I might be wrong, is there a way to load a view inside the master's template?
Thanks in advance

You couldn't render a view like that without ajax. {% load %} is used for loading modules, not templates or views, like:
{% load humanize %}
However, you could use an {% include %} tag, or a custom template tag that does whatever processing you need and returns its template where you include it.

Related

How can I prevent duplicate db queries when using Django's inclusion tag?

So imagine if I have widget that I registered as an inclusion tag like this:
#register.inclusion_tag('tags/widget.html', takes_context=True)
def widget(context):
return {'qs': Foo.objects.all(),
'request': context['request'],}
In the widget template I loop over some entries in the Foo object. I include the widget in my Mega Menu and my Footer. These templates are obviously split up. And included in base.html
However right now when I load the main page I hit the database twice for the same widget (Menu and Footer) so I get a duplicate query. How can I prevent something like this?
I like the idea of the inclusion tag but I don't want duplicate queries.
You can call your tag in base.html and save the data that it returns and then pass it to other sub templates that might need that data.
But i don't think you can use inclusion_tag anymore. You probably need to use something like simple_tag. Here is an example:
simple_tag:
#register.simple_tag
def widget(some_data):
return Foo.objects.all()
base template:
# You can access the result as foo_objs
{% widget some_data as foo_objs %}
# pass the data to other templates:
{% include "menu.html" with foo_objs=foo_objs %}
{% include "footer.html" with foo_objs=foo_objs %}
Now the widget function called once and data can be passed around.
Django docs on include

How do I use AJAX for pagination in Django-Tables2?

I am using django-tables2 and I am trying to display the data of the next page without loading another page. I think AJAX could be used.
From what I have found, it seems that it might not be possible.
There has been some discussion about this Support AJAX sorting/pagination
Is there something that I should look at to figure it out ?
It is possible however it's not so easy since django-tables2 (and django in general) are geared more to the Server Side Rendered world. I will sketch a solution here and consider that interesting topic for my blog (https://spapas.github.io):
You'll need to override the django-tables2 template that'll be used. You can't use the default one since the pagination to it is done by normal links. You should override it to use Ajax calls - take a look at this question for more Is it possible to custom django-tables2 template for a specific page in this case?. What you have to do is disable the default link functionality of the page links and call them through ajax. Depending on how you're going to do it this may be possible to be done through a script in your view's template without the need to override the table template at all.
You'll need to modify your view to detect if it's called by ajax (i.e through these pagination buttons you've defined above) or not and return a different template each time. If it's called normally then you'll just render your classic template. If it is called through ajax then it will return only the portion of the html that only contains the table.
Now in your normal template you'll put the table inside a div named (f.e) #the_table - when the user clicks on a pagination link you'll do the ajax call and the response will contain only the table - you'll then replace the contents of the #the_table div with what you just received.
So you should have two templates for your view, your view.html which will be something like:
{% extends base.html %}
{% block content %}
blah blah
<div id='the_table'>
{% include 'partial_table.html' %}
</div>
{% endblock %}
{% block extra_script %}
<script>
// You can do something like (NOT TESTED):
// I don't remember if the pagination links belong to a class
// if not you may want to add that class yourself
$('pagination-link').click(function(e) {
// Don't follow the link
e.preventDefault();
// Do the ajax request
$.get($(this).attr("href"), function(data) {
// Replace the table with what you received
$('#the_table').html(data)
});
});
</script>
{% endblock %}
And your partial_table.html:
{% load django_tables2 %}
{% render_table table %}
Now in your view if for example you are using CBVs then you'll have to use the template_name = view.html as defined above and override get_template_names like this:
def get_template_names(self):
# Sometimes the is_ajax() is not working properly so if it doesn't
# just pass the ajax_partial query parameter to your ajax request
if self.request.is_ajax() or self.request.GET.get('ajax_partial'):
return 'partial_table.html'
return super().get_template_names()
More info can be found in this recipe at my Django CBV guide: https://spapas.github.io/2018/03/19/comprehensive-django-cbv-guide/#implement-a-partial-ajax-view

Include template displaying a form

What I want to do is include a form from a separate template at the bottom of a given page, lets say; "example.com/listdataandform/".
The form-template "form.html" displays the form as it should when the view is included in the URLConf. So I can view with "example.com/form/"
What I have so far goes something like this:
{% extends "base/base.html" %}
{% block title %} page title {% endblock %}
{% block content %}
<h2>some "scene" data</h2>
<ul>
{% for scene in scenes %}
<li>{{ scene.scene }} - {{ scene.date }}</li>
{% endfor %}
</ul>
{% include "tasks/form.html"%}
{% endblock %}
The code inside "block content" works as it should, since it is defined with it's corresponding view for the url "example.com/listdataandform/".
{% include "tasks/form.html"%}: This only displays the submit button from form.html, as expected. I realize by only doing this: {% include "tasks/form.html"%}, the corresponding view method is never executed to provide the "form"-template with data.
Is there any way to this without having to define the view to a specific pattern in urls.py, so that the form can be used without going to the that specified URL..?
So I guess the more general question is; how to include templates and provide them with data generated from a view?
Thanks.
For occasions like this, where I have something that needs to be included on every (or almost every) page, I use a custom context processor, which I then add to the TEMPLATE_CONTEXT_PROCESSORS in settings.py. You can add your form to the context by using this method.
Example:
common.py (this goes in the same folder as settings.py)
from myapp.forms import MyForm
def context(request):
c = {}
c['myform'] = MyForm()
return c
You can also do any processing required for the form here.
Then add it in your settings.py file:
settings.py
.
.
TEMPLATE_CONTEXT_PROCESSORS = (
'''
All the processors that are already there
'''
"myproject.common.context",
)
.
.
I realize by only doing this: {% include "tasks/form.html"%}, the corresponding view method is never executed to provide the "form"-template with data.
Indeed. You included a template, and it really means "included" - ie: "execute in the current context". The template knows nothing about your views, not even what a "view" is.
How does this help me executing the view for the included template to provide it with form data?
It doesn't. A Django "view" is not "a fraction of a template", it's really a request handler, iow a piece of code that takes an HTTP request and returns an HTTP response.
Your have to provide the form to the context one way or another. The possible places are:
in the view
in a context processor (if using a RequestContext)
in a middleware if using a TemplateResponse AND the TemplateResponse has not been rendered yet
in a custom template tag
In all cases this will just insert the form in your template's context - you'll still have to take care of the form processing when it's posted. There are different ways to address this problem but from what I guess of your use case (adding the same form and processing to a couple differents views of your own app), using a custom TemplateResponse subclass taking care of the form's initialisation and processing might just be the ticket.

How to put multiple models on the same page?

I'm doing a website in html and base (where all pages extend) I want
to put a session of social network icons. As this session is base on
html it should be displayed on all pages of the website.
I do not want
to put this session in a static html, I want to do in django using
models. This is already done.
Question: Do I have to put the session of social network icons on each view, or can I make a separate view and all others extend this view?
How can I do this?
Try using an inclusion tag. You can create a function for doing all of the work to create the sessions and then associate that with a particular block of HTML.
templatetags/session.py
#register.inclusion_tag('includes/session_box.html')
def output_session_box(...):
...
return { .. }
The associated template file, includes/session_box.html, would have the HTML like any template.
And then your base.html would have:
{% load session %}
{% output_session_box ... %}
Use RequestContext and a context_processor to inject template variables into every view using RequestContext.
It's as simple as a python function accepting request as an arg, and returning a dictionary to be passed into your template.
https://docs.djangoproject.com/en/dev/ref/templates/api/#django.template.RequestContext
def my_processor(request):
return {'foo': 'bar'}
TEMPLATE_CONTEXT_PROCESSORS = (
# add path to your context processor here.
)
I generally have a per-project processor for the basics... It's exactly how django adds {{ user }} or {{ STATIC_URL }} to every template.

breadcrumbs using django admin templates

I have created a site mainly using django's admin interface, plus a few custom views. As the majority of the site is using the admin (and I am not to hot with css), I have just used django's admin tempates for my custom views (they are extended generic views).
Anyway, most of my custom views look good, and match the look and feel of the admin interface, but I don't know how to get the breadcrumbs working.
So form an extended generic view, how and what do I pass to the tempate's
{% block breadcrumb %}
tag?
I saw one article that mentioned the context object, but didn't have any further details.
If you want to provide breadcrumbs in your template and get breadcrumbs from parent template you can use block breadcrumbs & block.super variable in it:
{% block breadcrumbs %}{{ block.super }} › My custom site{% endblock %}
Or just pass to the template variable title.