Right number of rows, but they're empty - django

I'm trying to display some tables, but they come up empty. The part that gets me is the number of rows is correct, but they are completely blank. If the table has 9 entries, I get 9 empty rows.
The same code is working for a different table
tables.py:
class VouchersTable(tables.Table):
class meta:
model = Vouchers
fields = ('event_name', 'pk', 'valid_start', 'valid_end', 'lab_duration', 'user_email', 'redeem_date' )
views.py:
class ReportsView(LoginRequiredMixin, TemplateView):
template_name = 'reports.html'
def get_context_data(self, **kwargs):
context = super(ReportsView, self).get_context_data(**kwargs)
vouchers = VouchersTable(Vouchers.objects.all())
RequestConfig(self.request, paginate=False).configure(vouchers)
context['vouchers'] = vouchers
return context
reports.html:
{% extends "base.html" %}
{% load render_table from django_tables2 %}
{% block content %}
{% render_table vouchers %}
{% endblock content %}
models.py:
class Vouchers(models.Model):
creator_uid = models.IntegerField()
user_id = models.IntegerField()
username = models.CharField(max_length=255)
user_email = models.CharField(max_length=100)
event_name = models.CharField(max_length=255)
event_code = models.IntegerField()
valid_start = models.IntegerField()
valid_end = models.IntegerField()
redeemed = models.IntegerField()
redeem_date = models.IntegerField()
lab_version = models.CharField(max_length=40)
lab_model = models.IntegerField()
lab_id = models.IntegerField()
lab_duration = models.IntegerField()
resulting html (empty lines removed):
<div class="table-container">
<table>
<thead>
<tr>
</tr>
</thead>
<tbody>
<tr class="even">
</tr>
<tr class="odd">
</tr>
<tr class="even">
</tr>
<tr class="odd">
</tr>
<tr class="even">
</tr>
<tr class="odd">
</tr>
<tr class="even">
</tr>
<tr class="odd">
</tr>
<tr class="even">
</tr>
</tbody>
</table>
</div>

Oh well...
You've declared the table like this:
class VouchersTable(tables.Table):
class meta:
model = Vouchers
fields = ('event_name', 'pk', 'valid_start', 'valid_end', 'lab_duration', 'user_email', 'redeem_date' )
The correct way to write it is class Meta (Meta with a capital M): https://github.com/jieter/django-tables2

Related

How to check if the object is assigned to another object | Django

I am working on a django case like below:
models.py
class Room(models.Model):
name = models.CharField("Room No.",max_length=200)
class Meta:
verbose_name_plural = "Room"
def __str__(self):
return self.name
class Student(models.Model):
name = models.CharField("name",max_length=200)
father_name = models.CharField("father Name",max_length=200)
cell_no = models.CharField("cell No",max_length=200)
address = models.CharField("address",max_length=500)
room = models.ForeignKey(Room, on_delete=models.CASCADE, null=True, blank=True, related_name='all_rooms')
class Meta:
verbose_name_plural = "Student"
def __str__(self):
return self.name
views.py
def room(request):
allrooms= Room.objects.all()
form = RoomForm(request.POST or None, request.FILES or None)
if form.is_valid():
form.save()
messages.success(request, "Room added successfully.")
return redirect('/room')
context = {'allrooms':allrooms, 'form':form}
return render(request, 'room.html', context)
In templates in room.html I want to show the status Vacant/Occupied based on the fact if a room is assigned to some student or not. I have the following code in template but it shows 'Vacant' status for all rooms.
<table id="example1" class="table table-bordered table-striped">
<thead>
<tr>
<th>Room</th>
<th class="text-center">Status</th>
<th class="text-center">Action</th>
</tr>
</thead>
<tbody>
{% for room in allrooms %}
<tr>
<td>{{ room.name }}</td>
<td class="text-center">
{% if room.student_set.all %}
<small class="badge badge-danger">Occupied</small>
{% elif not room.student.all %}
<small class="badge badge-success">Vacant</small>
{% endif %}
</td>
<td class="text-center"><i class="fas fa-edit"></i></td>
</tr>
{% endfor %}
</tbody>
</table>
Please help someone to show he status of the room.
to get assigned and unassigned rooms you have to write queries with respect to the related field(in this case the foreign key "all_rooms") as follows:
total_rooms = Room.objects.all().annotate(num_rooms=Count("all_rooms"))
assigned_rooms = total_rooms.filter(num_rooms__gt=0)
unassigned_rooms = total_rooms.exclude(num_rooms__gt=0)
On running, these queries will return the room instances:

Display Django Foreign key on webpage

I have three models.
class Supplier(models.Model):
name = models.CharField(max_length=200, null=True)
class Order(models.Model):
supplier = models.ForeignKey(Supplier, on_delete=models.CASCADE)
class Product(models.Model):
supplier = models.ForeignKey(Supplier, on_delete=models.CASCADE, null=True, blank=True)
on_order = models.ForeignKey(Order, on_delete=models.CASCADE, null=True, blank=True)
I can display a table of all the products of a given order. However, I cannot seem to render the name of that supplier on the html page like <h4> Supplier: {{order.supplier}}</h4>
this is the view:
def PurchaseOrder(request, pk_order):
orders = Order.objects.get(id=pk_order)
products = Product.objects.filter(
on_order_id=pk_order).prefetch_related('on_order')
total_products = products.count()
supplier = Product.objects.filter(on_order_id=pk_order).prefetch_related('on_order')
context = {
'supplier': supplier,
'products': products,
'orders': orders,
'total_products': total_products, }
return render(request, 'crmapp/purchase_order.html', context)
here is my template:
{% extends 'crmapp/base.html' %}
{% load static %}
{% block content %}
<div class='main-site>'>
<h4> Supplier: {order.supplier}}</h4> **<----Does not work**
<h5>Order Number: {{order.id}}</h5> **<----Does not work**
<h5>Created on: {{order.date_created | date:"d/m/Y"}}</h5> **<----Does not work**
<h6>Total Items on Order: {{total_products}}</h6>
<input type="search" placeholder="Search any field..." class="form-control search-input" data-table="customers-list"/>
<table class="table table js-sort-table mt32 customers-list" id='myTable'>
<thead class="table" >
<tr>
<th class='header' onclick="sortTable(0)" scope="col">ID</th>
<th class='header' onclick="sortTable(1)" scope="col">Description</th>
<th class='header' onclick="sortTable(2)" scope="col">Cost</th>
<th class='header' onclick="sortTable(3)" scope="col">Order Quantity</th>
</tr>
</thead>
<tbody>
<tr>
{% for product in products %}
<td> {{product.id}}</td>
<td><h6><strong>{{product.description}}</strong></h6></td>
<td>£{{product.costprice |floatformat:2}}</td>
<td>{{product.on_order_quantity |floatformat:0}}</td>
</tr>
</tbody>
{% endfor %}
{% endblock %}
I've tried so hard... and didn't get very far.
Please help...
in context you write "orders", but in template you ask for "order", which is not defined. Try
<h4> Supplier: {{orders.supplier}}</h4>

Print a project name in jinja template

I have the following models
AcsObject class
class AcsObjects(models.Model):
object_id = models.IntegerField(primary_key=True)
object_type = models.ForeignKey('AcsObjectTypes', db_column='object_type')
context = models.ForeignKey('self', blank=True, null=True)
security_inherit_p = models.BooleanField()
creation_user = models.IntegerField(blank=True, null=True)
Projects class
class ImProjects(models.Model):
project = models.ForeignKey('AcsObjects',related_name='project', on_delete=False, primary_key=True)
project_name = models.CharField(max_length=1000)
project_nr = models.CharField(max_length=100)
project_path = models.CharField(max_length=100)
TimesheetTasks class
class TimesheetTasks(models.Model):
task = models.ForeignKey('Projects', related_name='t_task', on_delete=False, primary_key=True)
uom = models.ForeignKey('Categories', related_name='u_uom', on_delete=False)
planned_units = models.FloatField(blank=True, null=True)
billable_units = models.FloatField(blank=True, null=True)
I wrote the following code into views.py file.
class TimesheetData(TemplateView):
template_name = 'timesheet.html'
def get_context_data(self, **kwargs):
context = super().get_context_data(**kwargs)
context["da"] = TimesheetTasks.objects.all()
return context
I want to print a project_name but it is giving me a task_id ( task_id and project_id are same) using jinja template.
timesheet.html
<body>
<p> {{da}} </p>
<table class="table table-light">
<thead class="thead-light">
<tr>
<th>Task </th>
</tr>
</thead>
<tbody>
{% for timesheet in da %}
<tr>
<td> {{timesheet.task}} </td>
</tr>
{% endfor %}
</tbody>
</table>
</body>
It is giving me a blank output
Output
That's simply just because you're not access to product_name field yet.
<tbody>
{% for timesheet in da %}
<tr>
<td> {{timesheet.task}} </td>
</tr>
{% endfor %}
</tbody>
With this, Jinja just render the task id (project id), because Jinja think that you're not need any other information but just the foreign key value. So to be able to see the project_name, you should use this instead: timesheet.task.project_name, it does the job.
<tbody>
{% for timesheet in da %}
<tr>
<td> {{timesheet.task.project_name}} </td>
</tr>
{% endfor %}
</tbody>
Just want to mention that this could lead to another issue (performance issue) when Jinja have to query the data when render the template. To get rid of that, consider to use select_related which is an API of Django Queryset, check it out and gain some experiment that API, it really useful when using Django.

How to use an atribbute of an object Many To Many?

I'm using Django 2.1
I've got these 2 models with a ManyToMany relationship:
class Ingrediente(models.Model):
produtor = models.ForeignKey('auth.User', on_delete=models.CASCADE, default=10)
nome = models.CharField(max_length=200)
descricao = models.TextField()
quantidade = models.DecimalField(max_digits=10, decimal_places=3)
custo = models.DecimalField(max_digits=10, decimal_places=2)
def __str__(self):
return self.nome
e
class Produto(models.Model):
nome = models.CharField(max_length=200)
descricao = models.TextField()
ingredientes = models.ManyToManyField(Ingrediente)
utilitarios = models.ManyToManyField(OutrosCustos)
def __str__(self):
return self.nome
I use the this view to return a list with all objects of Class Produto:
def produtos_list(request):
produtos = Produto.objects.filter()
return render(request, 'egg_app/produtos_list.html', {'produtos':produtos})
And in my template I write this:
<table class="table">
<thead>
<tr>
<th scope="col">Nº Produto</th>
<th scope="col">Nome</th>
<th scope="col">Ingredientes</th>
<th scope="col">Custo</th>
</tr>
</thead>
<tbody>
{% for p in produtos %}
<tr>
<th scope="row">{{ p.pk }}</th>
<td>{{ p.nome }}</td>
<td>{{ p.ingredientes }}</td>
<td>custo teste</td>
</tr>
{% endfor %}
</tbody>
</table>
But my result in the column Ingredientes has been egg_app.Ingrediente.None and not the name of the Ingrediente of the relationship (between Ingrediente and Produto). In my Django admin page, I associate this, so I'm sure about the relationship.

Using radio button control to select foreign key pointing to an item in nested inline formset

I have the following classes defined that essentially define a Node class. Each Node can have multiple NodeIntf's assigned to it. Each NodeIntf can have multiple NodeIntfIpaddr's assigned to it. One of those NodeIntfIpaddr's maybe assigned as the mgmt_ipaddr attribute on the Node object. And one of them maybe assigned to the mgmt_ipaddr_v6 attribute. Now in my template, I have essentially a nested table for the interfaces and I want to use a radio button selector to choose which of the ipaddrs is selected for the mgmt_ipaddr(_v6) attributes on the Node object, but I'm not quite sure how to do it. I think that, as I iterate over the ipaddr_formset, I have to check to see if that ipaddr represents the selected mgmt_ipaddr, but I'm not sure how to do that. Any help would be appreciated.
class Node(models.Model):
name = models.CharField(max_length=64, primary_key=True)
mgmt_ipaddr = models.ForeignKey('NodeIntfIpaddr', null=True, on_delete=models.SET_NULL)
mgmt_ipaddr_v6 = models.ForeignKey('NodeIntfIpaddr', null=True, on_delete=models.SET_NULL)
class NodeIntf(models.Model):
intf = models.CharField(max_length=32)
node = models.ForeignKey('Node', on_delete=models.CASCADE)
class Meta:
unique_together = ('node', 'intf')
class NodeIntfIpaddr(models.Model):
node_intf = models.ForeignKey('NodeIntf', on_delete=models.CASCADE)
ipaddr = InetAddressField()
class Meta:
unique_together = ('node_intf', 'ipaddr')
class NodeForm(ModelForm):
class Meta:
model = Node
class NodeIntfForm(ModelForm):
class Meta:
model = NodeIntf
class NodeIntfIpAddrForm(ModelForm):
class Meta:
model = NodeIntfIpaddr
NodeIntfIpaddrFormSet = modelformset_factory(NodeIntfIpaddr,
form=NodeIntfIpAddrForm, extra=0)
class BaseNodeIntfFormSet(BaseInlineFormSet):
def add_fields(self, form, index):
super(BaseNodeIntfFormSet, self).add_fields(form, index)
instance = self.get_queryset()[index]
pk_value = instance.pk
form.ipaddr_formset = NodeIntfIpaddrFormSet(
queryset=NodeIntfIpaddr.objects.filter(node_intf=pk_value),
prefix='INTF_%s' % pk_value)
NodeIntfFormSet = inlineformset_factory(Node, NodeIntf,
form=NodeIntfForm, formset=BaseNodeIntfFormSet, extra=0)
class NodeUpdateView(UpdateView):
form_class = NodeForm
model = Node
def get_context_data(self, **kwargs):
c = super(NodeUpdateView, self).get_context_data(**kwargs)
node = self.get_object()
c['action'] = reverse('node-update', kwargs={'pk': node.name})
if self.request.POST:
node_intfs = NodeIntfFormSet(self.request.POST, instance=node)
if node_intfs.is_valid():
addrs = node_intfs.save_all()
else:
node_intfs = NodeIntfFormSet(instance=node)
c['node_intfs_formset'] = node_intfs
return c
Template snippet:
<table class='node_intfs'>
<thead>
<tr class='node_intf'>
<th colspan='2'></th>
<th>Name</th>
<th></th>
</tr>
<tr class='node_intf_ipaddr'>
<th>IPv4 Mgmt<br><label><input type='radio' name='mgmt_ipaddr' value=''{{ node.mgmt_ipaddr|yesno:', checked' }}>None</label></th>
<th>IPv6 Mgmt<br><label><input type='radio' name='mgmt_ipaddr_v6' value=''{{ node.mgmt_ipaddr_v6|yesno:', checked' }}>None</label></th>
<th colspan='2'></th>
</tr>
</thead>
<tbody>
{% for node_intf_form in node_intfs_formset %}
<tr class='node_intf'>
<td colspan='2'></td>
<td>{{ node_intf_form.intf }}</td>
<td></td>
</tr>
{% if node_intf_form.ipaddr_formset %}
{% for ipaddr_form in node_intf_form.ipaddr_formset %}
<tr class='node_intf_ipaddr'>
<td>TODO</td> <---- These are what I can't figure out
<td>TODO</td> <---- These are what I can't figure out
<td></td>
<td>{{ ipaddr_form.ipaddr }}</td>
</tr>
{% endfor %}
{% endif %}
{% endfor %}
</tbody>
</table>
I was able to do what I needed by using the following in my template:
<td class='center'><input type='radio' name='mgmt_ipaddr' value='{{ ipaddr_form.instance.id }}'{% if node.mgmt_ipaddr_id == ipaddr_form.instance.id %} checked='checked'{% endif %}</td>
<td class='center'><input type='radio' name='mgmt_ipaddr_v6' value='{{ ipaddr_form.instance.id }}'{% if node.mgmt_ipaddr_v6_id == ipaddr_form.instance.id %} checked='checked'{% endif %}</td>
This compares the mgmt_ipaddr(_v6)_id from the Node object with the id of the instance tied to the individual ipaddr forms, accessible as ipaddr_form.instance.id.
Just for completeness, I was also previously missing the management_form for each of the node_intf_forms and ipaddr_forms.