Accessing variable context name in template - django

I'm just discovering Django and i'm still a total noob.
I got a view that return multiple query set.
class RouteDateView(ListView):
model = Tblsummary
template_name = 'reviewrouteassess/selectdaterange.html'
def get_context_data(self, *args, **kwargs):
context = super(RouteDateView, self).get_context_data(*args, **kwargs)
context['allroute'] = Tblsummary.objects.filter(off_no=self.request.GET.get('depotcode')[:4])
for p in context['allroute']:
context[p.res_route] = Tblsummary.objects.filter(res_route=p.res_route)
return context
Then in my template I would like to access those dynamically name context. That's where i'm stuck.
<table>
{% for a in allroute %}
<tr>
<td>{{ a.res_route }}</td>
<td>{{ a.hcalls }}</td>
</tr>
{% for d in a.res_route %}
<tr>
<td>{{ d.res_route }}</td>
<td>{{ d.hcalls }}</td>
</tr>
{% endfor %}
{% endfor %}
How can I evaluate a.res_route so that a.res_route return the context passed by the view?? Thanks you so much!!
{% for d in a.res_route %}

I would suggest adding a method to your model to access the second query:
class Tblsummary(models.Model):
... # or whatever is there currently
def sub_routes(self): # name this how you'd like
return Tblsummary.objects.filter(res_route=self.res_route)
And then in your template:
<table>
{% for a in allroute %}
<tr>
<td>{{ a.res_route }}</td>
<td>{{ a.hcalls }}</td>
</tr>
{% for d in a.sub_routes %}
<tr>
<td>{{ d.res_route }}</td>
<td>{{ d.hcalls }}</td>
</tr>
{% endfor %}
{% endfor %}
This isn't going to be ideal from an efficiency standpoint since the sub_routes query is called once per entry in allroute but right now allroute is limited to 4 results so that shouldn't be an issue in practice.

Related

Show string if value is None in template

If a value is None I would like to show a - rather than rendering None in the table.
However I get the following error:
Could not parse the remainder: ' or '-'' from 'employee.full_name or '-''
I'd like to avoid doing a ton of if else statements if possible.
Here's my code:
{% for employee in employees %}
<tr>
<td>{{employee.full_name or '-'}}</td>
<td>{{employee.position or '-'}}}</td>
<td>{{employee.dob or '-'}}}</td>
<td>{{employee.phone or '-'}}}</td>
<td>{{employee.email or '-'}}}</td>
<td>{{employee.address or '-'}}}</td>
<td>{{employee.joined or '-'}}}</td>
</tr>
{% endfor %}
The following Python code works as expected:
dog = None
print(dog or '-')
You can work with the |default_if_none template filter [Django-doc]:
{% for employee in employees %}
<tr>
<td>{{ employee.full_name|default_if_none:'-' }}</td>
<td>{{ employee.position|default_if_none:'-' }}</td>
<td>{{ employee.dob|default_if_none:'-' }}</td>
<td>{{ employee.phone|default_if_none:'-' }}</td>
<td>{{ employee.email|default_if_none:'-' }}</td>
<td>{{ employee.address|default_if_none:'-' }}</td>
<td>{{ employee.joined|default_if_none:'-' }}</td>
</tr>
{% endfor %}

How to filter data displayed in a table in django?

I have a project where when a user enters a vehicle no, the database is filtered and a table containing that vehicle no and the information corresponding to is displayed. I further want to filter this displayed table, eg: if the user chooses to see quantity greater than 18kl, then the matching vehicle number with quantity greater than 18 is displayed. Also I want to hide the columns selected by the users as there are many columns. Can someone tell me how to do this in django, or suggest some better ways. (I am providing only the related code snippet.)
forms.py
class VehicleSearch(forms.Form):
vehicl[![enter image description here][1]][1]e_no = forms.CharField(widget=forms.TextInput(attrs={'class': 'special'}), required=False)
#filter form
class Filter(forms.Form):
capacity_grp = forms.ChoiceField(label='Show only', widget=forms.RadioSelect,
choices=[('abv', '>18 kl'), ('blw', '<18 kl')], required=False)
views.py
def search(request):
form_1 = forms.VehicleSearch()
if request.method == 'POST' and 'btnform1' in request.POST:
form_1 = forms.VehicleSearch(request.POST)
if form_1.is_valid():
vehicle_no = form_1.cleaned_data['vehicle_no']
transport = models.Transport.objects.filter(vehicle=vehicle_no)
my_dict.update({'transport': transport})
return render(request, 'search.html', my_dict)
search.html
/Vehicle form/
<form id="f1" method="POST">
{% csrf_token %}
{{form_1.as_p}}
<p style="padding: 10px;"><button class="myButton" name="btnform1">Search</button></p>
</form>
/*Table display*/
<div class="submain">
{% if transport %}
<table id="transportation">
<thead>
<th>Vehicle</th>
<th>Carrier</th>
<th>Location No</th>
<th>MCMU</th>
<th>Location</th>
<th>Customer Code</th>
<th>Zone</th>
<th>Quantity</th>
<th>RTKM</th>
<th>KL* KM</th>
<th>Amount</th>
<th>Load</th>
<th>Capacity</th>
<th>Rate</th>
<th>Cost</th>
</thead>
{% for i in transport %}
<tr class="item">
<td>{{ i.vehicle }}</td>
<td>{{ i.carrier }}</td>
<td>{{ i.location_no }}</td>
<td>{{ i.mcmu }}</td>
<td>{{ i.location }}</td>
<td>{{ i.customer_code }}</td>
<td>{{ i.zone }}</td>
<td>{{ i.quantity }}</td>
<td>{{ i.rtkm }}</td>
<td>{{ i.klkm }}</td>
<td>{{ i.amount }}</td>
<td>{{ i.load }}</td>
<td>{{ i.capacity }}</td>
<td>{{ i.rate }}</td>
<td>{{ i.cost }}</td>
</tr>
{% endfor %}
</table>
</div>
In the table display you can add a loop with the name's field, something like that:
View:
def search(request):
form_1 = forms.VehicleSearch()
if request.method == 'POST' and 'btnform1' in request.POST:
form_1 = forms.VehicleSearch(request.POST)
columns = request.POST.getlist('filter_hide_columns')
if form_1.is_valid():
vehicle_no = form_1.cleaned_data['vehicle_no']
transport = models.Transport.objects.filter(vehicle=vehicle_no)
my_dict.update({'transport': transport}, {'columns': columns})
return render(request, 'search.html', my_dict)
TemplateTag
def lookup(model, attr):
if hasattr(model, attr):
return getattr(model, attr)
else:
return None
refer https://docs.djangoproject.com/en/2.2/howto/custom-template-tags/
Template:
{% if transport %}
<table id="transportation">
<thead>
<tr>
{% for field in columns %}
<th>{{ field.name }}</th>
{% endfor %}
</tr>
</thead>
<tbody>
{% for t in transport %}
<tr>
{% for field in columns %}
<td>{{ t|lookup:field.name }}</td>
{% endfor %}
</tr>
{% endfor %}
</tbody>
</table>
{% endif %}
Please refer https://docs.djangoproject.com/en/2.2/topics/forms/#looping-over-the-form-s-fields

django display in html

I have two classes in my models:
class FicheFormation(models.Model):
intitule=models.TextField(blank=False,null=False)
duree=models.IntegerField(blank=False,null=False)
objective=models.TextField(blank=False,null=False)
niveau=models.TextField(blank=False,null=False)
prix=models.IntegerField(blank=False,null=False)
comptecf=models.ForeignKey('CompteRF',related_name='fichecompte',null=False)
unite= models.ManyToManyField('UniteFormation', related_name='unitefiche')
and
class UniteFormation(models.Model):
nomUe=models.TextField(blank=False,null=False)
acronyme=models.TextField(blank=False,null=False)
commentaire=models.TextField(blank=True,null=True)
and I want to display the list of formations of a comptecf,
so i write in my view this method:
def getFormation(request):
# user = request.user
# if user and user.is_active:
# u=user.username
c=CompteRF.objects.all().filter(username='Me')
queryset=FicheFormation.objects.all().filter(comptecf=c)
return render_to_response('formation.html', {'formations':queryset},
context_instance=RequestContext(request))
and in my formations.html:
% for car in formations %}
<tr>
<td>{{ car.intitule}}</td>
<td>{{ car.objective }}</td>
<td>{{ car.unite }}</td>
</tr>
{% endfor %}
update:
{% for car in formations %}
<tr>
<td>{{ car.intitule}}</td>
<td>{{ car.objective }}</td>
% for car in formations %}
<td>{{ car.unite.nomUe }}</td>
{% endfor %}
</tr>
{% endfor %}
it works for =car.intitule and car.objective but for car.unite it displays None, I haven't understand why because normaly it displays unite 'Sarra', in the console I need to do : c=unite.all() and then c[0].nomUe and it works and affich 'Sara' but in my view or html when i try to iterate on car.unite I have en error message !
To loop through the related unite objects, you need to loop through car.unite.all(). In the template, you drop the parentheses, so you do something like:
<td>{% for unite in car.unite.all %}{{ unite.nomUe }}{% endfor %}</td>

Django Master/Detail Template

I have a two classes that define two models
class Master(models.Model):
date = models.DateTimeField()
status = models.CharField(default = 'R')
class Detail(models.Model):
name = models.TextField()
from = models.ForeignKey(Master)
The view:
def list_view(request):
masters = master.objects.filter()
context = {'masters': masters}
return render_to_response('list.html', context, context_instance = RequestContext(request))
The template:
{% for master in masters %}
<tr>
<td>{{ master.date }}</td>
<td>{{ master.status }}</td>
<td>{# THIS #}</td>
</tr>
{% endfor %}
I want to show detail names in {# THIS #} section, but I don't know how to modify the View for that. How can I access to details for the master in template?
You can do something like this to get the names
{% for master in masters %}
<tr>
<td>{{ master.date }}</td>
<td>{{ master.status }}</td>
<td>
{% for detail in master.detail_set.all %}
{{detail.name}}<br/>
{% endfor %}
</td>
</tr>
{% endfor %}

Grouping models in template

I have two related models:
class Package(models.Model):
package_name = models.CharField(max_length=64)
ptype = models.CharField(max_length=16)
class Extra(models.Model):
package = models.ForeignKey(Package, related_name='package')
data = models.DecimalField(max_digits=8, decimal_places=2, blank=True, null=True)
information = models.CharField(max_length=1024, blank=True)
view.py:
def show_package(request):
list = get_list_or_404(Package, ptype='sometype')
return render(request, 'table.html', {'list': list})
and template:
{% for row in list %}
<table class="provider_list">
<tr>
<td>{{ row.package_name}}</td>
<td>{{ row.ptype }}</td>
</tr>
</table>
{% endfor %}
How can I add an additional table (from Extra model) next to the prelated table?
Like:
<table>
{% for extra_row in extra_list %}
<tr>
<td>{{ extra_row.data }}</td>
<td>{{ extra_row.information }}</td>
</tr>
{% endfor %}
</table>
Thanks.
try this:
{% for package in list %}
<table class="provider_list">
<tr>
<td>{{ package.package_name}}</td>
<td>{{ package.ptype }}</td>
<td>
<!-- fetch the related data -->
<table>
{% for extra in package.extra_set.all %}
<tr>
<td>{{ extra.data }}</td>
<td>{{ extra.information }}</td>
</tr>
{% endfor %}
</table>
</td>
</tr>
</table>
{% endfor %}
You show modify your Extra related_name on package ForeignKey.
models.py
class Extra(models.Model):
extra = models.ForeignKey(Package,related_name='extra_related_name') #default for related_name would be 'extra_set'
You can access all extra fields via:
extras = list.extra_related_name.all()
Let's imagine you have only one extra existing on every Package model
views.py
def show_package(request):
list = get_list_or_404(Package, ptype='sometype')
list.extra = list.extra_related_name.all()[0]
return render(request, 'table.html', {'list': list})
template
{% for row in list %}
<table class="provider_list">
<tr>
<td>{{ row.package_name}}</td>
<td>{{ row.ptype }}</td>
<td>{{ row.extra.data }}</td>
<td>{{ row.extra.information }}</td>
</tr>
</table>
{% endfor %}
If you are sure that there is at most one extra per package you should look at OneToOneField for easier access. If you are unsure, stick to ForeignKey and add checks in the view to check that you are accessing valid data.