Use variable in statement in template - django

I want to use a variable in {% include %} statement in django templates. Specifically, I am trying to include a template in another template and i need to generate and pass url to be used in a button. How can I achieve this?
This is my troublesome part of form.html template:
<div class="col-md-12">
{% url 'accountant:gp_taxes:delete_rate' pk=field.value as delete_url %}
{% include 'includes/formset_inline.html' with delete_url=delete_url %}
</div>
and formset_inline.html:
<a class="btn btn-s btn-danger" href="{{ delete_url }}">
<i class="fa fa-trash-o" aria-hidden="true"></i>
</a>
When I look at the url in my browser it is empty (I have <a class="btn btn-s btn-danger" href>).
How can I pass the url?
EDIT clarification for topic added.

I would suggest writing inclusion tag https://docs.djangoproject.com/en/1.11/howto/custom-template-tags/#inclusion-tags
#register.inclusion_tag('includes/formset_inline.html')
def formset_inline(delete_url):
return {'delete_url': delete_url}
And then
<div class="col-md-12">
{% url 'accountant:gp_taxes:delete_rate' pk=field.value as delete_url %}
{% formset_inline delete_url %}
</div>

Related

Django Calculation inside HTML

I wanted to do something simmilar to this suing django. but somehow i it doesn't work. how do i fix it?
for statik in statistik{
print(statik*total/100)
}
Is there any documentation regarding what I'm trying to implement to my django app? Thank you
Here's the HTML :
{% if statistics %}
{% for statik in statistics|slice:":4" %}
<div class="mb-3">
<div class="small text-gray-500">{{ statik.name }}
<div class="small float-right"><b>{{ statik.voters }} of {{ total }} Voters</b></div>
</div>
<div class="progress" style="height: 12px;">
<div class="progress-bar bg-success" role="progressbar" style="width: {{ statik.voters * total/100 }}%" aria-valuenow="50"
aria-valuemin="0" aria-valuemax="100"></div>
</div>
</div>
{% endfor %}
{% else %} <p>END TABLE</p>
{% endif %}
It is recommended you do calculations of any sort in view and pass it in context.
If you still want to go this route there are no math template tags except add included so you should create custom template tags or use django-mathfilters

Django - Displaying a user list takes over 14 seconds, how to speed it up?

I have a view that will display members based on the letter someone select(ex: clicking L on the webpage will display all the members whose firstname start with L, ordered by lastname)
The problem is that it can take over 14 seconds to display the page(like"M", around 180 members to list, 17 seconds or so to do so.) . The SQL query doesn't seems the problem since Debug Toolbar reports that it takes less than a second for the query.
Here is the view:
def show_all_members(request, letter):
members = MyUsers.objects.filter(firstname__istartswith=letter).order_by('lastname')
alphabet = list(string.ascii_lowercase)
request.session['url'] = request.get_full_path()
context_dict = {'all_members': members, 'alphabet': alphabet}
return render(request, "users/show_all_members.html", context_dict)
Programming is a hobby so I'm a bit lost on what is happening here and how to optimize it. Any help and pointer is appreciated.
Using Django 2.1.1
Edit: Here is the template. It shows if the member has bought punchcards or access passes and also a link to his profile.
{% extends "base.html" %}
{% load staticfiles %}
{% load i18n %}
{% block title %}Members{% endblock %}
{% block content %}
<div class="container">
<div class="page-header" xmlns="http://www.w3.org/1999/html">
<h2>Tribe members list</h2>
{% for l in alphabet %}
<a href="{% url 'users:show_all_members' l %}" class="btn btn-success">
{{ l }}
</a>
{% endfor %}
</div>
<br>
{% for user in all_members %}
<div class="row">
<p>
<div class="col-md-2">
<a href="{% url 'users:member_info' user.id %}" >
<h7>{{ user.fullname }}</h7>
</a>
</div>
<div class="col-md-1">
<a class="btn btn-warning btn-sm" href="{% url 'users:edit_profile_full' user.id %}"> Edit Profile</a>
</div>
<div class="col-md-6">
<a class="btn btn-success btn-sm" href="{% url 'classes:buy_pass' user.id %}"> Current PC/SP</a>
{%if user.punchcardbyuser_set.all %}
{%for pc in user.punchcardbyuser_set.all %}
<span class="badge badge-primary" >{{ pc.cardclasstype.name }}:{{ pc.classes }}</span>
{%endfor%}
{% endif %}
{%if user.allaccesspassbyuser_set.all %}
{%for aap in user.allaccesspassbyuser_set.all %}
<span class="badge badge-danger">AAP:{{ aap.classes }}</span>
{%endfor%}
{% endif %}
{%if user.seasonpass_set.all %}
/
{%for sp in user.seasonpass_set.all %}
<span class="badge badge-primary">{{ sp.label }}</span>
{%endfor%}
{% endif %}
</div>
<div class="col-md-3">
<a class="btn btn-success btn-sm" href="{% url 'classes:buy_pass' user.id %}"> Buy passes</a>
<a class="btn btn-primary btn-sm" href="{% url 'users:detail' user.username %}">Class attended: {{user.classes_set.all|length}}</a>
</div>
</p>
</div>
{% endfor %}
</div>
{% endblock content %}
Thanks to #Willem Van Onsem tips, I read on Django N+1 and it was indeed the problem. I had 747 queries in total...(!) (The page does display alot of informations from different M2M relations.) By reading on "prefetch_related" and some fiddling, it is now down to 7 and the page now loads in 1.2 seconds max. I'm sure I could get it lower by learning more about optimizing queries.
members = MyUsers.objects.filter(firstname__istartswith=letter).order_by('lastname').prefetch_related("punchcardbyuser_set").prefetch_related("classes_set").\
prefetch_related("allaccesspassbyuser_set").prefetch_related("seasonpass_set")
Thanks!

Django 1.11: pass id to url to generate detail view

I've a list of "nanas" (babysitters) that I render correctly. Now I need that when someone clicks on one of them , a detail page (for only the clicked nana opens).
I think my problem is on my template for all the Nanas, in the href:
<a href="{% url 'app-administrador:nana' nana.id %}">
Or in the Urls.
All Nanas page:
This is listing nanas View:
class NanasView(View):
def get(self, request):
nanas = Nana.objects.all()
context = {'nanas': nanas}
return render(request, 'app_administrador/nanas-registradas.html', context)
It's URL:
url(r'^referencias_de_nanas', views.NanasReferenciasView.as_view(), name='referencias_de_nanas'),
All Nanas templates:
{% extends 'app_administrador/templates/base.html' %}
{% load staticfiles %}
{% block content %}
<!-- Member Entries -->
{% for nana in nanas %}
<!-- Single Member -->
<div class="member-entry">
<a href="extra-timeline.html" class="member-img">
<i class="entypo-forward"></i>
</a>
<div class="member-details">
<a href="{% url 'app-administrador:nana' nana.id %}">
<h4>
<p href="extra-timeline.html">{{ nana.nombre }} {{ nana.apellido_paterno }} {{ nana.apellido_materno }}</p>
{% if nana.foto %}
<img src="{{ nana.foto.url }}" class="img-rounded" width="160px"/>
{% endif %}
</h4>
<!-- Details with Icons -->
<div class="row info-list">
<div class="col-sm-4">
<i class="entypo-briefcase"></i>
<a href={{ nana.antecedentes_policiales }}>Antecedentes policiales</a>
</div>
<div class="col-sm-4">
<i class="entypo-twitter"></i>
#johnnie
</div>
<div class="col-sm-4">
<i class="entypo-facebook"></i>
fb.me/johnnie
</div>
<div class="clear"></div>
<div class="col-sm-4">
<i class="entypo-location"></i>
{{ nana.direccion }}
</div>
<div class="col-sm-4">
<i class="entypo-mail"></i>
{{ nana.correo }}
</div>
<div class="col-sm-4">
<i class="entypo-linkedin"></i>
johnkennedy
</div>
</div>
</a>
</div>
</div>
{% endfor %}
{% endblock %}
Nana's detail page:
My try on showing the detail page for clicked nana:
class NanasValidarReferenciasView(View):
def get(self, request, nana_id):
# nana_id_is = nana_id
nana = Nana.objects.get(id=nana_id)
context = {'nana': nana}
return render(request, 'app_administrador/validar-referencias-nana.html', context)
It's URL:
url(r'^nana', views.NanasValidarReferenciasView.as_view(), name='nana'),
You see your href looks like this: <a href="{% url 'app-administrador:nana' nana.id %}"> which is totally fine. This means that the url link adds the two string together into one address. I don't know exactly how your urls are set up so it could look something like this:
root_url/2
Where root_url is whatever you have and 2 is the nana.id. To pass that to the url-view, it needs to accept any integer variable. Something like this:
urls.py
url(r'^nana/(?P<nana_id>\d+)/$', views.nanas_specific, name='nana'),
The P stands for Parameter, and it uses Regex logic if you want to look that up.
Then in your views, you can have a function ready to accept the parameter:
views.py
def nanas_specific(request, nana_id):
Where nana_id contains the result from the urls parsing.
I mostly work with function based views, but I'm assuming the same logic applies to classbased views. The id is not part of the URL and hence is not passed on. Change the url to
url(r'^nana/(?P<nana_id>\d+)/$', views.NanasValidarReferenciasView.as_view(), name='nana'),

django delete model entry from selected form option

I have the following form displaying entries of a model for user settings. When selected, I would like that a button catches its pk and send it to a Delete view.Here is the current code but I am missing this part.
user_detail template html
<form id="SettingsListForm"><label>&nbsp Settings List : &nbsp &nbsp &nbsp</label>
{% if user.usersetting.first %}
<select class="form-control" name="settingslist" id = "settingslist" form="SettingsListForm" >
{% for settings in user.usersetting.all %}
<option value="{{ settings.file.url }}">{{ settings }}
</option>
{% endfor %}
</select>
{% else %}
<li class="list-group-item">NO SETTINGS YET</li>
{% endif %}
<button class="btn btn-outline-light btn-circle"><i class="glyphicon glyphicon-minus" href="{% url 'my_app:setting_delete' pk=user.usersetting.last.id %}"></i></button>
{% block delete_setting_confirm_block %}
{% endblock %}
</form>
setting_confirm_delete html template with delete_setting_confirm_block
{% extends 'login_app/user_detail.html' %}
{% block delete_setting_confirm_block %}
<h4>
ARE YOU <b>REALLY</b> SURE YOU WANT TO <b>DELETE</b> THIS SETTING ?
<form method="POST">
{% csrf_token %}
<button type="submit" class="btn btn-outline-light btn-danger" value="Delete">YES</button>
<a class="btn btn-outline-light btn-default" href="{% url 'login_app:user_detail' pk=user.id %}"><b>NO</b></a>
</form>
</h4>
{% endblock %}
my_app urls
url(r'^setting/(?P<pk>\d+)/$',views.UserSettingDeleteView.as_view(),name='setting_delete'),
UserSettingDeleteView in my_app views
class UserSettingDeleteView(DeleteView):
model = models.UserSetting
template_name = 'my_app/setting_confirm_delete.html'
def get_success_url(self):
return reverse('my_app:user_detail', kwargs={'pk': self.object.user.pk})
Somehow, a similar technique works fine when using listgroups:
working sample in user_detail html
<ul class="list-group">
{% if user.userdata.first %}
{% for data in user.userdata.all %}
<li class="list-group-item">{{ data }}<a class="btn btn-outline-light btn-circle" href="{% url 'my_app:data_delete' pk=data.pk %}"><i class="glyphicon glyphicon-remove"></i></a></i></li>
{% endfor %}
{% block delete_data_confirm_block %}
{% endblock %}
{% else %}
<li class="list-group-item">NOTHING RECORDED YET</li>
{% endif %}
</ul>
In your template.html, you should create a form for deletion, like this:
<form action="{% url 'my_app:setting_delete' pk=user.usersetting.last.id %}" method="post">
{% csrf_token %}
<input type="submit" value="Delete" class="btn btn-outline-light btn-circle">
</form>
Because in HTML you can not send directly PUT or DELETE, you should fake it via a POST request. It will be useful to read this, it is explained well.
Your UserSettingDeleteView can be as simple as that:
from django.views.generic.edit import DeleteView
from django.urls import reverse_lazy
class UserSettingDeleteView(DeleteView):
model = MyModel
# Replace with the model you want to delete (User)
success_url = reverse_lazy('my_app:setting_list')
# After deletion, possibly you will want to redirect the user to the list view
The built-in DeleteView cares itself to find your model by the pk parameter you pass through your url and delete it, you just have to configure the model and success_url fields.
Now if you click on your Delete button, you should expect your desired entry to be deleted and the user to be redirected to the list view.
EDIT:
I forgot that you want to get this entry via options. Here you will have to use some JavaScript in order to find the currently selected element and send it's pk to your DeleteView.
At first, add id's to your option tags, like this:
<select class="form-control" name="settingslist" id="settingslist" form="SettingsListForm">
{% for settings in user.usersetting.all %}
<option value="{{ settings.file.url }}" id="{{ settings.id }}">{{ settings }}</option>
{% endfor %}
</select>
And then add some jQuery:
var settingId = $('#SettingsListName').find(":selected").attr('id');
In the end, you need to send settingId to the corresponding url, but I am not very familiar with JavaScript.
Try putting a hidden input in your form. Right now, nothing is passing through the form.
<input type="hidden" name="del_setting" value="{{user.usersetting.last.id}}">
So your form would look like this
<form method="POST">
{% csrf_token %}
<input type="hidden" name="del_setting" value="{{user.usersetting.last.id}}">
<button type="submit" class="btn btn-outline-light btn-danger" value="Delete">YES</button>
<a class="btn btn-outline-light btn-default" href="{% url 'login_app:user_detail' pk=user.id %}"><b>NO</b></a>
</form>
You also probably should move this out of the current form in your user detail template so that you're not putting a form within a form:
{% block delete_setting_confirm_block %}
{% endblock %}
None of the previously mentioned solutions would work so I guess the problem is the nested bootstrap select item which is supposed to display the pk of the setting.
For simplicity I then removed the problem by using list-group instead
<ul class="list-group">
{% if user.usersetting.first %}
{% for settings in user.usersetting.all %}
<li class="list-group-item">{{ settings }}<a class="btn btn-outline-light btn-circle" href="{% url 'my_app:setting_delete' pk=settings.pk %}"><i class="glyphicon glyphicon-remove"></i></a></li>
{% endfor %}
<label>Create a new setting...</label>
<a class="btn btn-outline-light btn-circle"><i class="glyphicon glyphicon-plus"></i></a>
{% else %}
<li class="list-group-item">Create a new setting...<a class="btn btn-outline-light btn-circle"><i class="glyphicon glyphicon-plus"></i></a></li>
{% endif %}
{% block delete_setting_confirm_block %}
{% endblock %}
</ul>
As a workaround,this works well.

include bootstrap modal template with template tags

I'm trying to create a bootstrap modal that can be included in my html files since I'm putting forms in modal and I don't want to create a new mdoal everytime.
It works fine, except for trying to include the form. Which is of course the important part. How could I include a template context variable inside a template tag?
modal_base
{% load crispy_forms_tags %}
<div id="{{ modal_form_id }}" class="modal fade" ariahidden="True">
<div class="modal-dialog">
<div class="modal-content">
<div class="modal-header">
<a class="close" data-dismiss="modal">X</a>
<h1 style="text-align:center;">
{{ modal_form_title }}
</h1>
</div>
<div class="modal-body">
<form method="{{modal_form_method|default:'POST'}}" action="{{modal_form_action}}">
{% csrf_token %}
{{ form|crispy }}
<input class="btn btn-primary" type="submit" value="Create"/>
</form>
</div>
<div class="modal-footer">
<a href="#" class="btn btn-danger" data-dismiss="modal">
Cancel
</a>
</div>
</div>
</div>
</div>
Example include in some html file:
{% include 'modal_form.html' with modal_form_id="new-category" modal_form_title="Create a New Category" modal_form_method="POST" modal_form_action="/home/" form={{category_form}} %}
form = {{category_form}} is the issue. Is there a way to get around this?
The modal renders fine, opens closes etc I just can't pass in the form
You're close! the only thing missing is that you don't need the curly braces to include it within the include tag
{% include 'modal_form.html' with modal_form_id="new-category" modal_form_title="Create a New Category" modal_form_method="POST" modal_form_action="/home/" form=category_form %}