Django template re-rendering - python

So I have a django DetailView that I can easily render by getting all the data that I need from get_context_data in my class based view. But the problem is that each time to render this template I would need to choose a date in this template, get the date somehow and then re-render that same template from the date picked.
I've been googling how to make this happen, there are something I could maybe do with AJAX, but maybe there is something easier to try, because I have little to no experience with AJAX/JS stuff
class PlaceDetailView(LoginRequiredMixin, PermissionCheckMixin, PlaceViewMixin, DetailView):
template_name = "places/place_detail.html"
def get_context_data(self, **kwargs):
context = super(PlaceDetailView, self).get_context_data(**kwargs)
place = context.get("object")
contract = Contract.objects.filter(pk=place.id).first()
context["renter"] = User.objects.filter(pk=contract.renter_id).first()
now = timezone.now()
meters = MeterInstallation.objects.filter(places=place.id)
context["active_meters"] = meters.filter(active_until__gte=now)
context["old_meters"] = meters.filter(active_until__lt=now)
context["services"] = ServiceTask.objects.filter(place=place)
# Need to add more context values from more models, but the date has to be given, how?
return context
place_detail_view = PlaceDetailView.as_view()
<div class="tab-pane fade show active" id="values" role="tabpanel" aria-labelledby="values-tab">
{% if values %}
<div class="table-responsive-sm">
<table class="table small">
<thead>
<tr>
<th scope="col">#</th>
<th scope="col">Values</th>
</tr>
</thead>
<tbody>
{% for value in values %}
<tr>
<th scope="row">{{ forloop.counter }}</th>
<!-- todo add needed values (type, values from/to, diff, tariff, total_price) -->
</tr>
{% endfor %}
</tbody>
</table>
</div>
{% else %}
No values.
{% endif %}
</div>
I would like to know is there an option to re-render this template when a date is being picked? Or maybe there is a better option to make this happen?:)

Related

context must be a dict rather than module

When I am filtering for my search bar I am getting this error. I am not sure what I am doing wrong here
Watching this tutorial: https://www.youtube.com/watch?v=llbtoQTt4qw&t=3399s
views.py
class pplList(LoginRequiredMixin,ListView):
model = People
context_object_name = 'people'
def get_context_data(self, **kwargs):
search_input = self.get.GET.get('search-area') or ''
if search_input:
context['people'] = context['people'].filter(name__icontains=search_input)
return context
people_list.html
{%if request.user.is_authenticated %}
<p>{{request.user}}</p>
Logout
{% else %}
Login
{% endif %}
<hr>
<h1>Interviewee Dashboard {{color}}</h1>
Add Candidates
<form method="get">
<input type = 'text' name = 'search-are'>
<input type = 'submit' value = 'Search'>
</form>
<table>
<tr>
<th> Item</th>
<th> </th>
</tr>
{% for people in people %}
<tr>
<td>{{people.name}}</td>
<td>View</td>
<td>Edit</td>
<td>Delete</td>
</tr>
{% empty %}
<h3>No items in list</h3>
{% endfor %}
</table>
There are some minor mistakes such as it should be self.request.GET.get('search-area'), also you haven't called the super() method, so try this view:
class pplList(LoginRequiredMixin,ListView):
model = People
context_object_name = 'people_list'
def get_context_data(self, **kwargs):
context=super().get_context_data(**kwargs)
search_input = self.request.GET.get('search-area', False)
if search_input:
context['people']= People.objects.filter(name__icontains=search_input)
return context
In the Html, the field name search-are and you are accessing in the view as self.request.GET.get('serach-area', False) kindly change its name to search-area` in the input tag of Html.
Also, class based views are generally written in PascalCase as they are classes of Python and requires their name to be written as model name as prefix and actual view name as suffix, so it should be PeopleListView.

How to download an updated file by admin in Django

what i am trying to do is:
Admin uploads a PDF file from admin panel. (1)
It needs to go to the specified template. (2)
And it should be downloaded by pressing download button in the template.
So here are codes:
(1)
class Reports(models.Model):
name = models.CharField(max_length=100, null=False, blank=False, verbose_name="File Name")
report = models.FileField()
(2)
<tr>
<td>"File Name must be showed in here"</td>
<td class="text-center">PDF</td>
<td class="text-center lang-tr-src"><i class="fas fa-file-download"></i></td>
<td class="text-center lang-en-src"><i class="fas fa-file-download"></i></td>
</tr>
In the website there will be one report for every month. I want to list them in the template and make them downloadable.
Should i write a view for that(if yes how it should be?) or what should i do?
Every single data you want to show to your template you need write it in your views.py, so this case is so specefic.
views.py:
def your_view_name(request):
reports = Reports.objects.all()
context = {
'reports': reports
}
return render(request, 'your_template.html', context)
Then make a url for your view in urls.py
urlpatterns = [
path("", views.your_view_name, name='your_url_name')
]
Your template:
<tr>
{% for obj in reports %}
<td>{{ obj.name }}</td>
<td class="text-center">PDF</td>
<td class="text-center lang-tr-src"><a href="{{ obj.report.url }}" Download
target="_blank"><i class="fas fa-file-download"></i></a></td>
<td class="text-center lang-en-src"><a href="" target="_blank"><i
class="fas fa-file-download"></i></a></td>
{% endfor %}
</tr>
create a new view firstly.
def report_view(request):
context = {}
reports= Reports.objects.all()
context['reports'] = reports
return render(request, "pages/report.html", context)
create an url for this view in urls.py
path('reports', report_view, name='report_view'),
in your template create forloop for this context like below:
{% for report in reports %}
<tr>
<td>"File Name must be showed in here"</td>
<td class="text-center">PDF</td>
<td class="text-center lang-tr-src"><i class="fas fa-file-download"></i></td>
<td class="text-center lang-en-src"><i class="fas fa-file-download"></i></td>
</tr>
{% endfor %}

converting and multiply float to int in django templates

I am fetching some data from a stocks API and I get some values (stored in the DB as float)
as follow:
YTD Change 0.379996
daily % change 0.00854
my view is as follow:
def get_stock(request):
empty = True
localStocks = Stock.objects.all()
if len(localStocks) > 0 :
empty = False
return render (request,'get_stock.html',{'empty':empty, 'output':list(localStocks)})
and my template
<section class="section-typography container u-readable">
<table>
<thead>
<tr>
<th>Ticker</th>
<th>Name</th>
<th>Price</th>
<th>Last Time</th>
<th>% Change</th>
<th>52W High</th>
<th>52W Low</th>
<th>YTD Change</th>
</tr>
</thead>
<tbody>
{% if not empty %}
{% for list_item in output %}
<tr>
<td> {{list_item.symbol }}</td>
<td> {{ list_item.companyName }}</td>
<td> {{ list_item.latestPrice }}</td>
<td> {{ list_item.latestTime }}</td>
<td> {{ list_item.changePercent }}</td>
<td> {{ list_item.week52High }}</td>
<td> {{ list_item.week52Low}}</td>
<td> {{ list_item.ytdChange }}</td>
</tr>
{% endfor %}
{% endif %}
</tbody>
</table>
</section>
{% endblock %}
the % change for the stock YTD is not 0.379996 but 37.99% and this is what I would like to display. Similarly the daily change is not 0.00854 but 0.85% . How can I manipulate the date either on the view or template to basically multiply it and display only the first 2 decimals of the float?
You need to implement a custom template tag. In your app directory create a new module named templatetags. Inside this module there should be a blank __init__.py and a random named file like percentage.py.
Your percentage.py should contain:
#percentage.py
from django import template
register = template.Library()
#register.simple_tag(name="percentage")
def percentage(value):
return str(round(value *100,2))+'%'
In any html file you want to use this tag, you should load this tag at the start of the file with {% load percentage %}. In order to pass the required value to the templatetag, you need to use it like: {% percentage list_item.changePercent %}
The best way is to change the value in view as follow:
YTD_to_pass = ((YTD*10000)//1/100)
this will multiply the value by 100 and keep 2 digits after whole number
then simply add a % symbol in template.

Dynamically render matrix like form in Django

I am using a Django model to represent day-hour combinations. The goal is to render a matrix-like form with the days on the x-axis and the hours on the y-axis. The user can check each combination to define when a vehicle is available during a week.
The model looks as follows:
class TimeMatrix(models.Model):
MO00 = models.BooleanField(default=False)
MO01 = models.BooleanField(default=False)
MO02 = models.BooleanField(default=False)
MO03 = models.BooleanField(default=False)
....
SO22 = models.BooleanField(default=False)
SO23 = models.BooleanField(default=False)
I like to render the corresponding form coming from the CreateView as the mentioned matrix. The html to do this requires a list of days = ['MON', 'TUE', ..., 'SUN'] and hours = ['00', '01', ..., '23'] in order to render the form dynamically. The following html shows this without using the form the Django CreateView provides:
<form action="#">
<div class="table-responsive">
<table class="table">
<thead class="thead-light">
<tr>
<th scope="col">Day</th>
{% for h in hours %}
<th scope="col">{{h}}</th>
{% endfor %}
</tr>
</thead>
<tbody>
{% for d in days %}
<tr>
<th scope="row" class="wt-col">{{d}}</th>
{% for h in hours %}
<td><input type="checkbox" name="{{d}}{{h}}" value="{{d}}{{h}}" id="id_{{d}}{{h}}"></td>
{% endfor %}
</tr>
{% endfor %}
</tbody>
</table>
</div>
</form>
Since I like to use the security measures build into Django forms I like this to make use of the form the CreateView provides. Following this explanation, the individual form can be accessed using form.<field_name>. Combining this with the html would require a dynamic way to access the form fields, which for me raises two questions:
Following this advice I was able to implement getattr functionality for the templates which works with my models, but fails on the form the CreateView provides (e.g. {{form|getattribute:'MON00'}}). What am I missing?
Since I cannot concat the day and hour string in the template ({{form|getattribute:d+h}} will not work), what is a suitable way to access the required form field?

Django form field issue with model formset

I'm having an issue with rendering individual form fields in a template. I have a model formset that I'm re-ordering after creation to make displaying a little easier on the template. Nothing too complicated, but rendering the form fields isn't working. You can see in the template where I try and render {{ form.train }}, but nothing shows up in the output. However, the form is definitely there because {{ form.instance.user.name }} works correctly.
I opened up PDB and inspected the form variable that I'm adding into the dictionary, and it says <django.forms.widgets.ScheduleForm object at 0x10c58bc50>. I'm not sure if that helps or not, but I wanted to provide as much info as possible.
The Model Form
class ScheduleForm(ModelForm):
class Meta:
model = models.Schedule
fields = [
'train',
'semi',
'tri_axle',
'flow_boy',
'misc',
'material',
'notes'
]
views.py
formset_fields = ('train','semi','tri_axle','flow_boy','misc','material','notes')
ScheduleFormSet = modelformset_factory(models.Schedule, fields=formset_fields, extra=0)
formset = ScheduleFormSet(queryset=queryset)
# Getting form in the right format
ordered_forms = {}
for form in formset:
# Make sure the job exists on the object
if not form.instance.job.number in ordered_forms:
ordered_forms[form.instance.job.number] = {}
# Make sure the user exists on the object
if not form.instance.user.name in ordered_forms[form.instance.job.number]:
ordered_forms[form.instance.job.number][form.instance.user.name] = []
# Append to correct place.
ordered_forms[form.instance.job.number][form.instance.user.name].append(form)
# Dict will look like
# { 'jobID' : { 'user' : [form1,form2,form3] } }
Template
{% for job, users in ordered_forms.items %}
<h2>{{ job }}</h2>
{% for user, forms in users %}
<table class='table striped'>
<thead>
<tr>
<th>{{ user }}</th>
<th>Train</th>
<th>Semi</th>
<th>Tri-Axle</th>
<th>Flow Boy</th>
<th>Misc</th>
<th>Material</th>
<th>Notes</th>
<th></th>
</tr>
</thead>
<tbody>
{% for form in forms %}
<tr>
<td>{{ form.instance.broker.name }}</td>
<td>{{ form.train }}</td>
<td>Semi</td>
<td>Tri-Axle</td>
<td>Flow Boy</td>
<td>Misc</td>
<td>Material</td>
<td>Notes</td>
<td></td>
</tr>
{% endfor %}
</tbody>
</table>
{% endfor %}
{% endfor %}
Turns out I forgot to add .items to {% for user, forms in users %}.
{% for job, users in ordered_forms.items %}
<h2>{{ job }}</h2>
{% for user, forms in users.items %}
<table class='table striped'>
....
{% endfor %}
{% endfor %}

Categories

Resources