Why doesnt the If statement in django work? - django

I was working from an example of an 'if' statement, but for some reason I cannot get it to work.
I tried every possible statement in the 'if', but it seems as though nothing makes it true for the if statement to run. Instead the Else statement runs.
Sample
{% extends 'base.html' %}
{% block content %}
<h2>Hardware Inventory</h2>
{% if hardware %}
<table id="datatable">
<thead>
<tr>
<th>Name</th>
<th>Manufacturer</th>
<th>Category</th>
</tr>
</thead>
<tbody>
{% for item in hardware %}
<tr>
<td>{{ item.name }}</td>
<td>{{ item.manufacturer }}</td>
<td>{{ item.kind }}</td>
</tr>
{% endfor %}
</tbody>
</table>
{% else %}
<p>The inventory is empty.</p>
{% endif %}
{% endblock %}
Mine
{% extends 'base.html' %}
{% block content %}
<h2>News</h2>
{% if entry %}
{% for item in entry %}
<table id = "news">
<tr>
<td>{{ item.title }}</td>
<td>{{ item.body }}</td>
<td>{{ item.pub_date }}</td>
</tr>
</table>
{% endfor %}
{% else %}
<p>No News</p>
{% endif %}
{% endblock %}
My view.py for news, Im not sure how to write it correctly, but i tried different combinations, this one errors at the moment causes it to crash
def index(request):
return render_to_response('news/index.html', {'Entry': Entry}, context_instance=RequestContext(request))
def Entry(request):
Entry = Entry.objects.all().order_by('pub_date')
return render_to_response('news/Entry.html', {'item':item}, context_instance=RequestContext(request))

Make sure you're actually passing entry into the context. For example:
render_to_response('template.html', { 'entry': entry })
Unset variables behave as variables set to None in Django templates.
UPDATE:
Made some revisions to your view code; not even sure how you got to the template rendering with what you had.
Original:
def index(request):
return render_to_response('news/index.html', {'Entry': Entry}, context_instance=RequestContext(request))
def Entry(request):
Entry = Entry.objects.all().order_by('pub_date')
return render_to_response('news/Entry.html', {'item':item}, context_instance=RequestContext(request))
Modified:
def index(request):
entry = Entry.objects.all().order_by('pub_date')
return render_to_response('news/index.html', {'entry': entry}, context_instance=RequestContext(request))
I don't think you even needed the Entry method, so removed that. I kept your naming the same, but it's better form to call that variable entries since it's multiple items.

Related

Get all objects' django guardian permissions of the authenticated user in template

I have an application where I am using django-guardian for object-level permission. In my ListView, I am listing all my instances in a table. In each row, I need to show the edit button if the user has the permission to edit this object.
So, I doing something like:
{% extends "base.html" %}
{% load guardian_tags %}
{% block content %}
<table>
<thead>...</thead>
<tbody>
{% for i in items %}
<tr>
<td>{{ i.name }}</td>
<td>
{% get_obj_perms request.user for i as "i_perms" %} <!-- this one -->
{% if "change_item" in i_perms %}
Edit
{% endif %}
</td>
</tr>
{% endif %}
</tbody>
</table>
{% endblock %}
Problem
Doing it that way is not optimized solution from database-wise. This solution makes a database query for each object to get the user permissions. How can I do so but with a single hit to the database to get all the objects' user permissions?
I think you would need to use get_objects_for_user in your view and pass it in to your template via context, eg, in a function based view or as part of your get_extra_context() in a CBV
from guardian.shortcuts import get_objects_for_user
items = Item.objects.all()
permitted_items = get_objects_for_user(request.user, 'change_item', klass=items)
context['permitted_items'] = permitted_items
...
then in your template
{% for i in items %}
<tr>
<td>{{ i.name }}</td>
<td>
{% if i in permitted_items %}
Edit
{% endif %}
</td>
</tr>
{% endfor %}

Dynamically update table when creating new enty using HTMX

After recent success in some simple HTMX tasks I wanted to extend adamchainz django-htmx example by a modal field that updates a table dynamically. I am not sure if I am returning the right thing in render ... but my problem is, the table is not being updated. Only when I hit reload.
view:
class CreateProductView(TemplateView):
template_name = "app/product_create.html"
form_class = OrderForm
def get(self, request, *args, **kwargs):
return render(request, self.template_name, {'form': self.form_class()})
def post(self, request):
Product.objects.create(name = request.POST["name"], price = request.POST["price"])
part_template = "app/partial-rendering.html"
return render(request, part_template, {"base_template": "app/_partial.html"})
urls.py:
path("create/", views.CreateProductView.as_view(), name = 'create'),
This is my index.html with the table in it:
<div class="..."><button class="btn btn-primary"
id="showButton"
hx-get="/create"
hx-target="#modal-create">create</button</div>
<main role="main" id="main">{% include "app/orders_table.html" %}</main>
<div id="modal-create"></div>
I also have a partial-rendering.html in place:
{% extends base_template %}
{% block main %}
{% include "app/product_table.html" %}
{% endblock %}
and a _partial.html:
<main id="main">
{% block main %}{% endblock %}
</main>
I will not post the whole product_table.html here, I guess it is straight forward ... mainly:
<table class="table table-striped table-hover">
<thead>
<tr>
<th>product name</th>
<th>price</th>
</tr>
</thead>
<tbody>
{% for product in page.object_list %}
<tr>
<td>{{ product.name}}</td>
<td>{{ product.price }}</td>
</tr>
{% endfor %}
</tbody>
</table>
The data from the form is collected via JS and sent to django using AJAX. I did not use the normal form submit because I wanted to avoid a page reload (which would solve that problem, I know).
I did try to put this together from the example mentioned above. Everything except the dynamic page update runs well!
Some approach is to remove the div targeted:
<div id="modal-create"></div>
then in your table body write the id deleted:
<tbody id="modal-create">
you want some partial for your table loops
{% for product in page.object_list %}
{% include 'some_table_body_tr_partial.html' %}
{% endfor %}
your partial might contain something like this:
<tr hx-target="this" hx-swap="outerHTML">
<td>{{ product.name}}</td>
<td>{{ product.price }}</td>
</tr>
This approach have an issue: the width of the form will take the wide of the first column.

Django template - How to match model datefield with a date in date generator?

In my models.py Task can have multiple Employer so I use ManyToManyField
In my views.py I got a date generator - it return range of 2 weeks from current day.
So here is my template
<table>
<thead>
<tr>
<th>{% trans 'employer_id' %}</th>
{% for i in date_range %}
<th>{{ i }}</th>
{% endfor %}
</tr>
</thead>
<tbody>
{% for employer in employers %}
<tr>
<td>{{ employer.employer_id }}</td>
{% for t in employer.task_set.all %}
<td>{{ t }}</td>
{% empty %}
<td>0</td>
{% endfor %}
</tr>
{% endfor %}
</tbody>
</table>
What I need is when I create a Task and assign it to employers, it should show me in the html table a start_date of Task of each employers for specific days.
So far I got this with codes above:
^date of tasks of these employers are not matching with days in the table header.
Instead of
{% for t in employer.task_set.all %}
<td>{{ t }}</td>
{% empty %}
<td>0</td>
{% endfor %}
you need to iterate over the dates again, since you're not creating <td>'s for each date.
{% for i in date_range %}
{% for t in employer.task_set.all %}
{% if t.start_date == i %}
<td>{{ t }}</td>
{% else %}
<td>-</td>
{% endif %}
{% empty %}
<td>0</td>
{% endfor %}
{% endfor %}

Return an extra argument with the datachart

I'm trying to print a chart and to return an argument with the datachart to the template.
Views.py:
def errors(request):
totalErrors = total_errors()
table = table_errors()
return render_to_response('macaco_errores.djhtml', {'totalErrors': totalErrors, 'table': table})
There's no problem to print the chart without the 'table' argument, but with both I get 'False' in template when I load in "load_chart".
EDIT:
Template:
{% block head %}
{% load nvd3_tags %}
{% include_chart_jscss %}
{% load_chart charttype totalesData totalesContainer extra %}
{% endblock %}
{% block body %}
<div align="center">
<h1>Errors</h1>
{% include_container totalesContainer 600 1000 %}
</div>
<div align="center">
<table border="1">
<tr>
<th>Log</th>
<th>Type</th>
</tr>
{% for type,log,date in table.items %}
<tr>
<td>{{ type }}</td>
<td>{{ log }}</td>
</tr>
{% endfor %}
</table>
</div>
{% endblock %}
{% load_chart charttype totalesData totalesContainer extra %}
This tag is needing four variables in the context: charttype, totalesData, totalesContainer, extra
It appears you are not passing any of them from your view function (which provides only totalErrors and table)
So there is no way that this can work from the code you've posted.
See this example from the django-nvd3 docs for the type of context data you need to provide from your view function:
http://django-nvd3.readthedocs.org/en/latest/introduction.html#example-how-to-create-a-piechart
Please see also the Django docs for how to pass variables from the view function into the template for rendering.
For example in your view you are currently using the render_to_response helper which takes a dict of variable names and values to pass to the template... these are the only vars which are available in the template.
The solution was:
def counterroresmacaco(request):
errores = errores_macaco()
errores['tabla'] = tipoerror_ticker()
return render_to_response('macaco_errores.djhtml', errores)
'errores' is a dictionary, then in the template I use a for to iterate over 'tabla'.
The problem to pass two arguments (as I was doing) is that django-nvd3 doesn't recognize the arguments like in the examples.
{% load nvd3_tags %}
{% include_chart_jscss %}
{% load_chart charttype totalesData totalesContainer extra %}
{% include_container totalesContainer 600 1000 %}
<table border="1">
<tr>
<th>Tipo de log</th>
<th>Ticker</th>
</tr>
{% for reg in tabla %}
<tr>
<td>{{ reg.log }}</td>
<td>{{ reg.ticker }}</td>
</tr>
{% endfor %}
</table>

django template view nested list

i made a nested list and from that id like to make a table in my template
list looks something like
ground_skills_available = [[category1, [skill1, skill2, skill3]], [category1, [skill1, skill2]]]
Now i want to list it that you got category with below the items, next category and other items. Problem is, i have no clue about hot to show only category, instead of category +all items, since you cant seem to use the index of a list?
Can someone please help me out?
<table>
{% for categories in ground_skills_available %}
{% for category in categories %}
<tr>
<td>{{ category }}</td>
</tr>
{% for skill in category %}
<tr>
<td>{{ skill.name }}</td>
</tr>
{% endfor %}
{% endfor %}
{% endfor %}
Change your outer loop to
{% for category, skills in ground_skills_available %}
This technique is described in the Django for loop docs.
On the first iteration of the loop, this will take the list [category1, [skill1, skill2, skill3], and assign
category = category1
skills = [skill1, skill2, skill3]
You can then display {{ category }}, and loop through skills.
Putting that together, you have:
<table>
{% for category, skills in ground_skills_available %}
<tr>
<td>{{ category }}</td>
</tr>
{% for skill in skills %}
<tr>
<td>{{ skill.name }}</td>
</tr>
{% endfor %}
{% endfor %}
</table>
{% if forloop.index == 1 %} ... some code ... {% endif %}
or
{% if forloop.index0 == 0 %} ... some code ... {% endif %}
Expectation:
{% for categories in ground_skills_available %}
{% for category in categories %}
{% if forloop.first %}
<tr>
<td>{{ category }}</td>
</tr>
{% else %}
{% for skill in category %}
<tr>
<td>{{ skill.name }}</td>
</tr>
{% endfor %}
{% endif %}
{% endfor %}
{% endfor %}