Я пытаюсь вызвать метод в моих моделях для запуска, нажав URL-адрес. Когда он попадает, он возвращает и выдает сообщение об ошибке «неподдерживаемые типы операндов для -: 'datetime.datetime' и 'NoneType'".
views.py
from django.shortcuts import render
from rest_framework import viewsets
from .serializers import EntrySerializer
from .models import Entry
class EntryView(viewsets.ModelViewSet):
serializer_class = EntrySerializer
queryset = Entry.objects.all()
entryId = Entry.objects.filter(end_time__isnull=True).values('id')
# returns <QuerySet [{'id': 8}]>
for id in entryId:
entryIdNum = id['id']
#returns 8
entry = Entry()
def ToggleView(request):
entry.toggle_paused()
entry.save()
models.py
from django.db import models
from django.db.models import F, ExpressionWrapper, fields
from django.utils import timezone
from dateutil.relativedelta import relativedelta
from decimal import Decimal
class Entry(models.Model):
start_time = models.DateTimeField()
end_time = models.DateTimeField(blank=True, null=True, db_index=True)
seconds_paused = models.PositiveIntegerField(default=0)
pause_time = models.DateTimeField(blank=True, null=True)
comments = models.TextField(blank=True)
date_updated = models.DateTimeField(auto_now=True)
hours = models.DecimalField(max_digits=11, decimal_places=5, default=0)
def _str_(self):
return self.TUID
@property
def total_hours(self):
"""
Determined the total number of hours worked in this entry
"""
total = self.get_total_seconds() / 3600.0
# in case seconds paused are greater than the elapsed time
if total < 0:
total = 0
return total
@property
def is_paused(self):
"""
Determine whether or not this entry is paused
"""
return bool(self.pause_time)
def pause(self):
"""
If this entry is not paused, pause it.
"""
print('Pause Hit')
if not self.is_paused:
self.pause_time = timezone.now()
def pause_all(self):
"""
Pause all open entries
"""
entries = self.user.timepiece_entries.filter(end_time__isnull=True)
for entry in entries:
entry.pause()
entry.save()
def unpause(self, date=None):
print('Unpause Hit')
if self.is_paused:
if not date:
date = timezone.now()
delta = date - self.pause_time
self.seconds_paused += delta.seconds
self.pause_time = None
def toggle_paused(self):
"""
Toggle the paused state of this entry. If the entry is already paused,
it will be unpaused; if it is not paused, it will be paused.
"""
print('Toggle Pause Hit')
if self.is_paused:
self.unpause()
else:
self.pause()
def check_overlap(self, entry_b, **kwargs):
"""Return True if the two entries overlap."""
consider_pause = kwargs.get('pause', True)
entry_a = self
# if entries are open, consider them to be closed right now
if not entry_a.end_time or not entry_b.end_time:
return False
# Check the two entries against each other
start_inside = entry_a.start_time > entry_b.start_time \
and entry_a.start_time < entry_b.end_time
end_inside = entry_a.end_time > entry_b.start_time \
and entry_a.end_time < entry_b.end_time
a_is_inside = entry_a.start_time > entry_b.start_time \
and entry_a.end_time < entry_b.end_time
b_is_inside = entry_a.start_time < entry_b.start_time \
and entry_a.end_time > entry_b.end_time
overlap = start_inside or end_inside or a_is_inside or b_is_inside
if not consider_pause:
return overlap
else:
if overlap:
max_end = max(entry_a.end_time, entry_b.end_time)
min_start = min(entry_a.start_time, entry_b.start_time)
diff = max_end - min_start
diff = diff.seconds + diff.days * 86400
total = entry_a.get_total_seconds() + entry_b.get_total_seconds() - 1
if total >= diff:
return True
return False
def is_overlapping(self):
if self.start_time and self.end_time:
entries = self.user.timepiece_entries.filter(
Q(end_time__range=(self.start_time, self.end_time)) |
Q(start_time__range=(self.start_time, self.end_time)) |
Q(start_time__lte=self.start_time, end_time__gte=self.end_time)
)
totals = entries.aggregate(max=Max('end_time'), min=Min('start_time'))
totals['total'] = 0
for entry in entries:
totals['total'] = totals['total'] + entry.get_total_seconds()
totals['diff'] = totals['max'] - totals['min']
totals['diff'] = totals['diff'].seconds + \
totals['diff'].days * 86400
if totals['total'] > totals['diff']:
return True
else:
return False
else:
return None
def save(self, *args, **kwargs):
self.hours = Decimal('%.5f' % round(self.total_hours, 5))
super(Entry, self).save(*args, **kwargs)
def get_total_seconds(self):
"""
Determines the total number of seconds between the starting and
ending times of this entry. If the entry is paused, the end_time is
assumed to be the pause time. If the entry is active but not paused,
the end_time is assumed to be now.
"""
start = self.start_time
end = self.end_time
if not end:
if self.is_paused:
end = self.pause_time
print(end)
print('------------------')
else:
end = timezone.now()
delta = end - start
if self.is_paused:
# get_paused_seconds() takes elapsed time into account, which we do not want
# in this case, so subtract seconds_paused instead to account for previous pauses
seconds = delta.seconds - self.seconds_paused
else:
seconds = delta.seconds - self.get_paused_seconds()
return seconds + (delta.days * 86400)
Я знаю, что ошибка исходит из метода get_total_seconds (). Когда вызывается self.start_time, он возвращает объект Entry (None). Как я могу передать entryIdNum или entryId из представлений в модель, чтобы она знала, что такое self?