Why doesn't Django template show data correctly? - django

I'm a new Django programmer and I'm writing a learning app. This app have a foreign key relations and I use prefetch_related method. This system runs well ;-)
My problem is at the template, when I show the data from the table, the browser shows this menssages:
ID Bill number Warehouse Article Quantity Price (<<-- columns)
1 CabeceraDeFacturas object (1) Primer almacén Bolsa plástico .05 mm. KK. 10 1
...
The questions are:
¿Why does show the message "CabeceraDeFacturas object (1)" instead of a bill number?
¿Can I fix this? ¿How?
The information about is:
Part of models.py
class CabeceraDeFacturas(models.Model):
ID_cliente = models.ForeignKey('Clientes',on_delete=models.CASCADE)
fecha_factura = models.DateField('Fecha de factura: ')
ID_formaDePago = models.ForeignKey('FormasDePago',on_delete=models.CASCADE)
Porcentaje_IVA = models.PositiveSmallIntegerField(default=21)
Total_factura = models.IntegerField()
class Meta:
ordering = ('id',)
#def __str__(self):
# return self.id
class LineasDeFacturacion(models.Model):
ID_factura = models.ForeignKey('CabeceraDeFacturas',on_delete=models.CASCADE)
ID_almacen = models.ForeignKey('Almacen',on_delete=models.CASCADE)
ID_articulo = models.ForeignKey('Articulos',on_delete=models.CASCADE)
cantidad = models.IntegerField(default=1)
Precio = models.IntegerField()
class Meta:
default_related_name = 'lineas'
# def __str__(self):
# return str(self.ID_factura)
Part of views.py
class VerFacturaCompleta(ListView):
#model = CabeceraDeFacturas
model = LineasDeFacturacion
template_name = "ListarTodasLasFacturasConLineas.html"
# recuperar las facturas completas y líneas --> comprobar
# queryset = CabeceraDeFacturas.objects.all().select_related('lineas')
queryset = LineasDeFacturacion.objects.all().prefetch_related('ID_factura')
paginate_by = 10
And finally, the template:
<h1>Listar facturas</h1>
<table class="table">
<thead>
<tr>
<th scope="col">ID</th>
<th scope="col">Factura</th>
<th scope ="col">Almacén</th>
<th scope ="col">Artículo</th>
<th scope ="col">Cantidad</th>
<th scope="col">Precio</th>
<!--<th scope="col">Almacén</th>-->
</tr>
</thead>
<tbody>
{% for articulo in object_list %}
<tr>
<!--<th scope="row">{{ articulo.pk }}</th>-->
<th scope ="row"> {{ articulo.pk }} </th>
<td>{{ articulo.ID_factura }}</td>
<td>{{ articulo.ID_almacen }}</td>
<td>{{ articulo.ID_articulo }}</td>
<td>{{ articulo.cantidad }}</td>
<td>{{ articulo.Precio }}</td>
</tr>
{% endfor %}
</tbody>
</table>
<hr>
Thanks a lot!

Well, the template only uses "object_list". This object_list comes form a instruction like this "queryset = LineasDeFacturacion.objects.all().prefetch_related('ID_factura')"; which is in a view.
The view which I use for this template is the next:
class VerFacturaCompleta(ListView):
#model = CabeceraDeFacturas
model = LineasDeFacturacion
template_name = "ListarTodasLasFacturasConLineas.html"
# recuperar las facturas completas y líneas --> comprobar
# queryset = CabeceraDeFacturas.objects.all().select_related('lineas')
queryset = LineasDeFacturacion.objects.all().prefetch_related('ID_factura')
paginate_by = 10
I don't use a context inside the view, only, the view pass an object_list (queryset) to the template.
Thanks for your time!

I found the mistake. The problem was in the models.py declaration. The CabeceraDeFactura class didn't had a data return. When I fixed this mistake
def __str__(self):
return str(self.id)
the template shows the data correctly.
Thanks for your time!

Related

Using attribute from a related model django

At my work everyone has to plan until they've reached their planning target. To make this easier I'm building a planning tool to plan the activities. All the activities have standard durations which are saved in the PlanningActivity model. Now I want to show a list of all the planned activities with the standard duration and also sum up the total planned time in a week. How can I use strd_duration in my added Planning's? I've tried so much, but nothing seems to work...
models.py
class PlanningActivity(models.Model):
name = models.CharField(max_length=255)
is_billable = models.BooleanField()
is_auto_realised = models.BooleanField()
strd_duration = models.PositiveIntegerField()
def __str__(self):
return self.name
class Planning(models.Model):
added_by = models.ForeignKey(
User, related_name='planning_activity', on_delete=models.DO_NOTHING
)
activity = models.ForeignKey(
PlanningActivity, on_delete=models.DO_NOTHING
)
date = models.DateField()
note = models.CharField(max_length=255)
def __str__(self):
return str(self.id)
views.py
def home(request):
planning_form = PlanningForm(request.POST)
if request.user.is_authenticated:
planning = Planning.objects.filter(added_by=request.user).order_by('-date')
contracts = UserContract.objects.filter(assigned_user=request.user)
else:
planning = ''
contract = ''
if planning_form.is_valid():
new_planning = planning_form.save(commit=False)
new_planning.added_by = request.user
new_planning.save()
return redirect('/')
else:
planning_form = PlanningForm()
return render(request, 'home.html', {'planning_form': planning_form, 'planning':planning, 'contracts':contracts})
home.html
<table class="table table-striped mt-2">
<thead class="thead-light">
<tr>
<td>Activity</td>
<td>Date</td>
<td>Note</td>
<td>Duration</td>
</tr>
</thead>
<tbody>
{% for plan in planning %}
<tr>
<td>{{ plan.activity }}</td>
<td>{{ plan.date }}</td>
<td>{{ plan.note }}</td>
<td>{{ plan.activity_id }}</td> <== HERE I WANT TO SHOW strd_duration
</tr>
{% endfor %}
</tbody>
</table>
You can access the attribute through the foreign key:
{% for plan in planning %}
<tr>
<td>{{ plan.activity }}</td>
<td>{{ plan.date }}</td>
<td>{{ plan.note }}</td>
<td>{{ plan.activity.strd_duration }}</td>
</tr>
{% endfor %}
Note that in the view, you can optimize the number of queries to the database with a .select_related(…) clause [Django-doc]:
planning = Planning.objects.filter(
added_by=request.user
).select_related('activity').order_by('-date')

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.

How to set field value based on what user click in Django ListView

I have two models Parent and Child. I would like to display both values in a ListView, whereby there is an Add Child button for each family.
Supposed that the parents are already populated, when I click Add Child, I would love that in the form of Child, the parent field are already set to the corresponding family name (please see code below).
Simple model would be:
class Family(models.Model):
family_name = models.CharField(max_length=100, default='', blank=False)
father_name = models.CharField(max_length=100, blank=False, default='')
mother_name = models.CharField(max_length=100, blank=False, default='')
def get_absolute_url(self):
return reverse('family-list')
def __str__(self):
return str(self.family_name)
class Children(models.Model):
parent = models.ForeignKey(Family, blank=False, default=None, null=True, on_delete=models.PROTECT, related_name='their_child')
child_name = models.CharField('4Jet ID', max_length=100, default='', blank=False)
birth_date = models.DateField(default=timezone.now, blank=False)
def get_absolute_url(self):
return reverse('family-list') # both return to family list view
The View using simple generic view:
class FamilyList(ListView):
model = Family
template_name = '/family_list.html'
context_object_name = 'fam_list'
# class NewParent omitted
class NewChild(CreateView):
model = Children
template_name = '/child_new.html'
context_object_name = 'child'
fields = [
'parent', 'child_name', 'birth_date'
]
and the simplified template:
<!--file: family_list.html-->
{% for fam in fam_list %}
<table>
<tr>
<th class="header"></th>
<th class="header">Family Name</th>
<th class="header">Father's First Name</th>
<th class="header">Mother's First Name</th>
<th class="header">Add Child</th>
</tr>
<tr>
<td>+</td>
<td>{{ fam.family_name }}</td>
<td>{{ fam.father_name }}</td>
<td>{{ fam.versand_datum | date:"d M, Y" }}</td>
<td>Add Child
</td>
</tr>
<tr >
<td colspan="5">
<div>
<table>
<tr>
<th class="header">Child's First Name</th>
<th class="header">Date of Birth</th>
</tr>
{% for child in fam.their_child.all %}
<tr>
<td>{{ child.child_name }}</td>
<td>{{ child.birth_date | date:"d M, Y" }}</td>
</tr>
{% endfor %}
</table>
</div>
</td>
</tr>
</table>
{% endfor %}
I've tried playing with the get_initial method in the NewChild view but by setting pdb trace within the method, the self.request.GET.getlist() gives me empty list.
Again, I just want that when I click the Add Child button in the template, the parent field in the child form will be set corresponding to the parent that I clicked.
Any idea how to do that?
All help are much appreciated
Your template is only a template to wiew a result, not to record an other one.
You must write a form and the most simple to you is to follow the initial Django tutorial.
Url : https://docs.djangoproject.com/en/2.1/intro/tutorial04/
You need :
- write a form template
- write a service to record you form result.
- and write a new template to view your record.
Take the time to do the initial tutorial, it is simple to follow

How to filter today's date from ListView

I have models called Statistics. From views, I made a ListView to display it on the template. Now my problem is I would like to see only today's == date_expiry. How can I do this using ListView?
models.py
class Statistics(models.Model):
site = models.CharField(max_length=264)
name = models.CharField(max_length=264, blank=True)
mac_add = models.CharField(max_length=264)
minutes_used = models.CharField(max_length=265)
date = models.DateTimeField(auto_now=True, blank=True)
date_expiry = models.DateTimeField()
def __str__(self):
return self.name
views.py
class DisplayStats(ListView):
model = Statistics
ordering = ['date']
html
<table class="table">
<tr>
<th>Site</th>
<th>Name</th>
<th>Mac ID</th>
<th>Hours</th>
<th>Date</th>
<th>Date Expired</th>
</tr>
{% for clients in object_list %}
<tr>
<td>{{ clients.site }}</td>
<td>{{ clients.name }}</td>
<td>{{ clients.mac_add }}</td>
<td>{{ clients.minutes_used|cut:".0" }}</td>
<td>{{ clients.date }}</td>
<td>{{ clients.date_expiry }}</td>
</tr>
{% endfor %}
</table>
you can just filter it.
import datetime
class DisplayStats(ListView):
model = Statistics
ordering = ['date']
def get_queryset(self):
# python3
queryset = super().get_queryset()
# if python2
# queryset = super(DisplayStats, self).get_queryset()
queryset.filter(date_expiry=datetime.date.today())
return queryset
You can just filter the query set. You can do it two ways:
Override the queryset
import datetime
class DisplayStats(ListView):
model = Statistics
queryset = Statistics.objects.filter(date_expiry=datetime.date.today())
ordering = ['date']
Use get_queryset()
import datetime
class DisplayStats(ListView):
model = Statistics
ordering = ['date']
def get_queryset(self):
return Statistics.objects.filter(date_expiry=datetime.date.today())

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.