Hi, here is the template that is trying to render the cumulative_time. It is in line 32 inside the for loop.
I’m afraid it is all very much a work in progress, so a lot of print statements and not terribly succinct. Been trying to learn to code and thought try and add some extra features to what I leant in the Crash Course Book. Thanks again for taking the time to help.
below is topics.html
{% extends "flying_logs/base.html" %}
<h1>Topics</h1>
{% block page_header %}
{% endblock page_header %}
{% block content %}
<div class="container">
<table class="table text-center table-hover table-bordered" >
<tr><tr class="table-primary">
<th style="width: 10%">Lesson No.</th>
<th scope="col">Date</th>
<th scope="col">Lesson</th>
<th scope="col">Dual/Solo
<th scope="col">Flying time</th>
<th scope="col">Cumulative</th>
</tr>
</thead>
{% for topic in topics %}
{% if topic.solo_lesson %}
<tr class="table-success">
{% endif %}
<td class="text-center"> {{topic.lesson_number}}</td>
<td>{{ topic.date|date:'d/m/Y'}}</td>
<td><a href="{% url 'flying_logs:topic' topic.id %}">{{ topic }}</a></td>
<td>{{ topic.solo_lesson|yesno:"Solo, Dual" }}</td>
<td class="text-center">{{topic.lesson_time}}</td>
<td>Time so far{{ cumulative_time }}</td>
</tr>
{% endfor %}</table>
</div>
<div class="container">
<table class="table text-center table-hover table-bordered" >
<thread>
<tr><tr class="table-primary">
<th style="width: 5%">Solo</th>
<th style="width: 20%">Dual</th>
<th style="width: 20%">total time</th>
<th style="width: 20%">Time remaing</th>
<th style="width: 20%"> Solo Lessons</th>
<th style="width: 35%">Number of lessons</th>
</tr>
</thead>
<td>{{solo_time|floatformat:1}}</td>
<td>{{dual_time|floatformat:1}}</td>
<td>{{time}}</td>
{% if remaining_time >= 0 %}
<td class="table-danger">{{ remaining_time|floatformat:1 }}</td>
{% elif remaining_time <= 0 %}
<td class="table-success">You've done the minimum hours!!</td>
{% endif %}
<td class="text-center"> {{ solo_num}} </td>
<td>{{lessons}}</td>
</tr>
</tr>
</table>
</div>
<h3><a href="{% url 'flying_logs:new_topic' %}"><button name="new entry"
class="btn btn-primary">Add a new topic</button></a></h3>
{% if graph %}
<div style="width:600;height:500">
{{ graph|safe }}
</div>
{% endif %}
{% endblock content %}
Below is base.html
{% load bootstrap4 %}
<!doctype html>
<html lang="en">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1,
shrink-to-fit=no">
<title>Flying Log</title>
{% bootstrap_css %}
{% bootstrap_javascript jquery='full' %}
</head>
<body>
<nav class="navbar navbar-expand-md navbar-light bg-light mb-4 border">
<a class="navbar-brand" href="{% url 'flying_logs:index' %}">
Flying logs</a>
<button class="navbar-toggler" type="button" data-toggle="collapse"
data-target="#navbarCollapse" aria-controls="navbarCollapse"
aria-expanded="false" aria-label="Toggle navigation">
<span class="navbar-toggler-icon"></span></button>
<div class="collapse navbar-collapse" id="navbarCollapse">
<ul class="navbar-nav mr-auto">
<li class="nav-item">
<a class="nav-link" href="{% url 'flying_logs:topics' %}">
Topics</a></li>
</ul>
<ul class="navbar-nav ml-auto">
{% if user.is_authenticated %}
<li class="nav-item">
<span class="navbar-text">Hello, {{ user.username }}.</span>
</li>
<li class="nav-item">
<a class="nav-link" href="{% url 'users:logout' %}">Log out</a>
</li>
{% else %}
<li class="nav-item">
<a class="nav-link" href="{% url 'users:register' %}">Register</a>
</li>
<li class="nav-item">
<a class="nav-link" href="{% url 'users:login' %}">Log in</a></li>
{% endif %}
</ul>
</div>
</nav>
<main role="main" class="container">
<div class="pb-2 mb-2 border-bottom">
{% block page_header %}{% endblock page_header %}
</div>
<div>
{% block content %}{% endblock content %}
</div>
</main>
</body>
</html>
Here is the view.py
from django.shortcuts import render, redirect
from django.contrib.auth.decorators import login_required
from django.http import Http404
from django.shortcuts import render, redirect, get_object_or_404
from django.db.models import Q
from django.db.models import Sum
import json
import requests
import math
from datetime import date, time, datetime
from plotly.graph_objs import Bar, Layout, Pie
from plotly import offline
from .models import Lessontopic, Entry
from .forms import TopicForm, EntryForm
from django.conf import settings
from django.core.mail import send_mail
from django.db.models import Window, Sum, F, RowRange
from django.db.models.functions import Lead
# Create your views here.
def check_topic_owner(request, topic):
if topic.owner != request.user:
raise Http404
def _get_topics_for_user(user):
""" returns a queryset of topics the user can access """
q = Q(public=True)
if user.is_authenticated:
# adds user's own private topics to the query
q = q | Q(public=False, owner=user)
return Lessontopic.objects.filter(q)
def get_current_weather(request):
url = ('https://weather.visualcrossing.com/VisualCrossingWebServices/rest/services/timeline/taurangaaerodrome/today?unitGroup=metric&key=MZRCJUSM7DG5Z3TE8FPVNR4E4')
r = requests.get(url)
print(f'status code is {r.status_code}')
response_dict = r.json()
repo_dicts = response_dict['currentConditions']
repo_dict = repo_dicts['datetime'], repo_dicts['temp']
current_temp = repo_dicts['temp']
return response_dict
def last_lesson(request):
latest = Lessontopic.objects.latest('date')
latest_lesson = Lessontopic.objects.get(id=latest.id)
return latest_lesson
#@login_required
def index(request):
"""The home page for flying journal"""
the_last_lesson = last_lesson(request)
l_lesson_date = the_last_lesson.date.date()
x = the_last_lesson.date.time()
print( 'll', x)
print('\n time now:', datetime.now(),'\n')
days_since_last = str(datetime.now().date() - l_lesson_date)[:7]
abc = datetime.now().date()
print(abc)
print((days_since_last))
print('\nDAYS SINCE LAST LESSON', str(days_since_last))
print('CURRENRT',datetime.now())
time = Lessontopic.objects.aggregate(Sum('lesson_time'))
print('AAAAAA',time)
total_time = time.get('lesson_time__sum')
print('BBBBBBB', total_time)
total_time = float(total_time)
print(F'total flying time{total_time} hours')
lessons = Lessontopic.objects.all().count()
print(f"There has been {lessons} lessons ")
solo = (Lessontopic.objects.filter(solo_lesson=True)
.aggregate(Sum('lesson_time')))
solo_time = float(solo.get('lesson_time__sum'))
print(f"solo lesson flying time {solo_time} hours")
solo_num = Lessontopic.objects.filter(solo_lesson=True).all().count()
print(f'ther have been {solo_num} solo lessons')
get_weather = get_current_weather(request)
weather = get_weather['currentConditions']
future = get_weather['days']
ft = future[0]
forecast_max = ft['tempmax']
issue_time = weather['datetime']
current_temp = weather['temp']
wind_speed = weather['windspeed']
wind_direction = int(weather['winddir'])
current_conditions = weather['conditions']
context = {'time':total_time, 'lessons':lessons, 'solo_time':solo_time,
'solo_num':solo_num, 'weather':weather, 'current_temp':current_temp,
'issue_time':issue_time, 'wind_speed':wind_speed,
'wind_direction':wind_direction, 'current_conditions':current_conditions,
'forecast_max': forecast_max, 'the_last_lesson':the_last_lesson,
'days_since_last':days_since_last,}
#ModelName.objects.filter(field_name__isnull=True).aggregate(Sum('field_name'))
#print('hll')
return render(request, 'flying_logs/index.html', context)
#@login_required
def topics(request):
"""Show all the topics"""
# Get the public topics
public_topics = Lessontopic.objects.filter(public=True).order_by('date_added')
# Get the private topics
if request.user.is_authenticated:
private_topics = Lessontopic.objects.filter(owner=request.user).order_by('date_added')
topics = private_topics
"""By Adding private into topics, seeing all public topics not just users
this way any topic added by authenticated user comes up in private, even if
it is also visible in public"""
time = Lessontopic.objects.aggregate(Sum('lesson_time'))
total_time = time.get('lesson_time__sum')
total_time = float(total_time)
lessons = Lessontopic.objects.all().count()
print(f"There has been {lessons} lessons ")
solo = (Lessontopic.objects.filter(solo_lesson=True)
.aggregate(Sum('lesson_time')))
solo_time = solo.get('lesson_time__sum')
print(f"solo lesson flying time {solo_time} hours")
solo_num = Lessontopic.objects.filter(solo_lesson=True).all().count()
dual = (Lessontopic.objects.filter(solo_lesson=False)
.aggregate(Sum('lesson_time')))
dual_time = dual.get('lesson_time__sum')
remaining_time = 50 - total_time
#Make a pie chart.
labels = ['Solo', 'Dual']
values = [solo_time, dual_time]
chat = ['this is long']
# Visualise the results
data=[Pie(labels=labels,text=chat,values=values,pull=[0.1, 0],
textposition='outside')
]
x_axis_config = {'title': 'Hours'}
y_axis_config = {'title': 'Lesson type'}
my_layout = Layout(title='Flying time Solo vs Dual Instruction',title_font_color='black' ,
title_font_size=30, title_x=0.5, legend_bordercolor='green', legend_borderwidth=5 )
fig = ({'data': data, 'layout': my_layout})
div = offline.plot(fig, auto_open=False, output_type='div')
cumulative_time = Lessontopic.objects.annotate(
cumulative_times=Window(
expression = Sum('lesson_time'),
order_by=F('date_added').asc(),
frame=RowRange(start=None, end=0)
)
)
context = {'topics': topics, 'cumulative_time':cumulative_time,'lessons':lessons, 'solo_time':solo_time,
'solo_num':solo_num, 'dual_time':dual_time,'solo_num':solo_num,
'remaining_time':remaining_time, 'dual':dual,'graph':div,}
else:
topics = public_topics
context = {'topics': topics}
return render(request, 'flying_logs/topics.html', context)
#@login_required
def topic(request, topic_id):
"""Shpw a single topic and the entries associated with it"""
topics = _get_topics_for_user(request.user)
topic = get_object_or_404(topics, id=topic_id)
# Make sure the topic belongs to the current user.
#check_topic_owner(request, topic)
rd = topic.runway_direction
x = (str(topic.date)[:10])
#y = datetime.strptime(x, "%Y-%m-%d")
#print(y)
start_time = topic.time_of_lesson
if start_time < 10:
start_time = '0'+str(start_time)
else: start_time = str(start_time)
time = int(start_time) - 3
if time < 10 :
time = '0'+str(time)
else: time = str(time)
print('heres time:',time)
end_time = str(int(start_time) + 2)
#(type(time))
#('end timme:', end_time)
#(x)
date1 = x
#(date1)
# Removed the +13 as will fail once clocks chage= just checking to 20
date_string= date1 +'T'+str(start_time)+':00:00+'
#('...............',date_string)
#(date_string[20:])
url = ('https://weather.visualcrossing.com/VisualCrossingWebServices/rest/services/weatherdata/history?aggregateHours=1&combinationMethod=aggregate&startDateTime='+ date1 +'T'+ time + '%3A00%3A00&endDateTime='+ date1 +'T' + end_time +'%3A00%3A00&maxStations=-1&maxDistance=-1&contentType=json&unitGroup=metric&locationMode=single&key=MZRCJUSM7DG5Z3TE8FPVNR4E4&locations=tauranga')
r = requests.get(url)
#(f'status code is {r.status_code}')
response_dict = r.json()
repo_dicts = response_dict['location']
repo_dict = repo_dicts['values']
values = repo_dict
day_0 = values[0]
day_1 = values[1]
for x in values:
if x['datetimeStr'][:20] == date_string:
print('they match',x['datetimeStr'][:20],date_string)
day = x
break
elif x['datetimeStr'][:20] != date_string:
print('they dont match',x['datetimeStr'],date_string)
time_of_forecast = str(day['datetimeStr'][11:16])
print('forecast time',time_of_forecast)
temp = day['maxt']
wind = day['wspd']
knots = (wind*0.54)
knots = "{:.2f}".format(knots)
conditions = day['conditions']
wind_direction = int(day['wdir'])
#Calculate the crosswind
if wind_direction > rd:
angle = wind_direction - rd
print(angle, 'is the angle dir - rd')
print('radians',math.sin(math.radians(angle)))
print('normal', math.sin(angle))
print(math.sin(math.radians(90)))
print(math.sin(math.radians(30)))
else:
angle = rd - wind_direction
print(angle, ' is from rd - dir')
crosswind = ((math.sin(math.radians(angle))*wind)*(0.54))
crosswind_knots = "{:.2f}".format(crosswind)
print('the crosswind is:',crosswind)
print(conditions)
print('the temp ===',temp)
#t1 = Lessontopic.objects.get(temp)
entries = topic.entry_set.order_by('-date_added')
context = {'topic': topic, 'entries': entries, 'topics': topics, 'temp':temp,
'wind':wind, 'conditions':conditions,'wind_direction':wind_direction,
'rd':rd, 'knots':knots, 'crosswind_knots':crosswind_knots,
'time_of_forecast':time_of_forecast,
}
return render(request, 'flying_logs/topic.html', context)
@login_required
def new_topic(request):
"""Add a new topic."""
if request.method != 'POST' :
# No data submitted create a new blank form.
form = TopicForm()
else:
# POST data submitted; process the data.
form = TopicForm(data=request.POST)
if form.is_valid():
new_topic = form.save(commit=False)
new_topic.owner = request.user
new_topic.adding = 'does this work?'
new_topic.save()
return redirect ('flying_logs:topics')
# Dispalay a blank or invalid form.
context = {'form': form}
return render(request, 'flying_logs/new_topic.html', context)
@login_required
def new_entry(request, topic_id):
""" Add a new entry for a particualr topic"""
topic = get_object_or_404(Lessontopic, id=topic_id)
if request.method != 'POST':
# No data submitted; create a blank form
form = EntryForm()
else:
# POST data submitted; process the data.
form = EntryForm(data=request.POST)
if form.is_valid():
new_entry = form.save(commit=False)
new_entry.blahtopic = topic
new_entry.save()
return redirect('flying_logs:topic', topic_id=topic_id)
# Display a blank or invalid form.
context = {'topic':topic, 'form':form}
return render(request, 'flying_logs/new_entry.html', context)
#@login_required
def edit_entry(request, entry_id):
"""Edit an existing extry"""
entry = Entry.objects.get(id=entry_id)
topic = entry.blahtopic
check_topic_owner(request, topic)
if request.method != 'POST':
# Initial request; prefill the current form with current entry.
form = EntryForm(instance=entry)
else:
# POST data submitted; process the data
form = EntryForm(instance=entry, data=request.POST)
if form.is_valid():
form.save()
return redirect('flying_logs:topic', topic_id=topic.id)
context = {'entry': entry, 'topic':topic, 'form':form}
return render(request, 'flying_logs/edit_entry.html', context)
In case it helps this is my models.py file.
from django.db import models
from django.contrib.auth.models import User
from django.forms.widgets import DateInput
from django import forms
import json
import requests
# Create your models here.
class Lessontopic(models.Model):
"""The topic of each lesson or day flying"""
text= models.CharField(max_length=200)
date_added = models.DateTimeField(auto_now_add=True)
owner = models.ForeignKey(User, on_delete=models.CASCADE)
public = models.BooleanField(default=False, verbose_name="Make post public?",
help_text="click on this form if you want it to be viewed by anyone")
lesson_number = models.PositiveIntegerField(blank=True, null=True)
lesson_time = models.DecimalField('enter flight time', max_digits=2, decimal_places=1)
solo_lesson = models.BooleanField(default=False, verbose_name="Were you solo for the lesson",
help_text="Click if were flying solo for the lesson")
runway_direction = models.PositiveIntegerField(
verbose_name="Select runway direction: 07 or 25")
number_landings = models.PositiveIntegerField(blank=True, default=1,
help_text="Enter how many landings")
date = models.DateTimeField()
time_of_lesson = models.PositiveIntegerField(
verbose_name="time that the lesson started")
weather_data = models.CharField(max_length=200)
adding = models.TextField(default=None, null=True, blank=True)
def __str__(self):
"""Return a string representation of the modeel"""
return self.text
class Entry(models.Model):
"""Describe the lesson and add extra information"""
blahtopic = models.ForeignKey(Lessontopic, on_delete=models.CASCADE)
text = models.TextField()
to_improve = models.TextField()
date_added = models.DateTimeField(auto_now_add=True)
class Meta:
verbose_name_plural = 'entries'
def __str__(self):
"""Return a string representation of the model."""
if len(self.text) > 50 :
return f"{self.text[:50]}..."
else:
return f"{self.text}"