how to set default hour for my django datetimefield - django

im trying to set default hour to my django datetimefield , im using datetime-local in my input , but it shows current time , i want to set default time to 12:00 PM and changeable as well
i tried this but doesnt work
from datetime import datetime
def set_default_time_checkout():
now = datetime.now()
new_time = now.replace(hour=12, minute=0, second=0, microsecond=0)
return new_time
class Booking(models.Model):
check_in = models.DateTimeField(default=timezone.now)
check_out = models.DateTimeField(default=set_default_time_checkout,blank=True,null=True)
but doesnt work
and this is my forms.py
class BookingForm(forms.ModelForm):
check_in = forms.DateTimeField(required=True,input_formats=['%Y-%m-%dT%H:%M','%Y-%m-%dT%H:M%Z'],widget=forms.DateTimeInput(attrs={'type':'datetime-local'}))
check_out = forms.DateTimeField(initial=set_default_time_checkout, required=False,input_formats=['%Y-%m-%dT%H:%M','%Y-%m-%dT%H:M%Z'],widget=forms.DateTimeInput(attrs={'type':'datetime-local'}))
also the initial time doesnt work in the modelform is it possible please ? how to achieve it ? i tried these solutions from the question but none of them works
Can I set a specific default time for a Django datetime field?
thanks in advance

This might probably work:
import datetime
defualt=datetime.time(12, 0, 0)
The output of datetime.time() has hour, minute and second instances

Related

check if today is due date django

I have a model like this
class Tasks(models.Model):
title = models.CharField(max_length=100,null=True,blank=True)
due_date_time= models.DateTimeField(default=timezone.now)
As due date is a date and time field, how I can check if today is due date of this task , while I am saving time and date both
You can make use of the __date lookup [Django-doc]:
from django.utils.timezone import now
Tasks.objects.filter(
due_date_time__date=now().date()
)
or if you work with timezones, you can work with a range check:
from datetime import timedelta
from django.utils.timezone import now
today = now().replace(hour=0, minute=0, second=0, microsecond=0)
tomorrow = today + timedelta(days=1)
Tasks.objects.filter(
due_date_time__gte=today,
due_date_time__lt=tomorrow
)
Note: normally a Django model is given a singular name, so Task instead of Tasks.

Django model elapsed time between two DateTimeFields

I am pretty new to django and haven't been able to find a way to get the elapsed time between two DateTimeFields and save it to another model.
from django.db import models
class Timesheet(models.Model):
startTime = models.DateTimeField(auto_now_add=True)
endTime = models.DateTimeField(blank=True, null=True)
duration = models.DateTimeField(endTime - startTime)
def _str_(self):
return self.startTime
How can I make duration = endTime - startTime?
I am also using a PostgreSQL database.
I wouldn't use a dedicated model field for the duration.
I would use a property on the model instead for the same functionality.
Something like:
#property
def duration(self)
return self.end_time - self.startime
Lucas has a good idea of using an annotation, but if you have a Timesheet instance somewhere that didn't come from that object manager and was not previously annotated, you would have to do a separate database hit to actually annotate it.
This property is used as such:
some_timesheet_instance.duration
Use annotate() to compute the duration field at query time for each object in the queryset
from django.db.models import F, ExpressionWrapper, fields
timesheets = Timesheet.objects.annotate(
duration=ExpressionWrapper(
F('endTime') - F('startTime'),
output_field=fields.DurationField()
)
)
timesheets[0].duration # datetime.timedelta(0, 722, 18373)
Is possible perform another queryset methods over annotations like filter(), order_by(), aggregate(), etc.
timesheets.order_by('-duration')
timesheets.aggregate(Avg('duration')) # {'duration__avg': datetime.timedelta(0, 26473, 292625)}
duration = timesheet.end_time - timesheet.start_time
When you substract two datetime instances you don't get another datetime instance but a timedelta instace, which is just the days, seconds and microseconds difference between the two datetimes. You can't store a timedelta in a DateTimefield, but you can use an IntegerField, for example:
days_in_seconds = duration.days * 86400 # days difference by seconds in a day
duration_in_seconds = duration.seconds + days_in_seconds # duration in seconds
When you want to access the duration as timedelta you just do:
import datetime
duration = datetime.timedelta(seconds=timesheet.duration)
You can also store it as FloatField as suggested in this question.

Django/Python How do I get my receiver to add a value to a field relative to a previous addition - instead of indiscriminately adding to the value?

Python3.6.4; Django 2.0. Long time first time, please be gentle
I'm creating a tracking application that accepts multiple work logs to a work order. I'm trying to track time spent on a workorder by obtaining a time delta from each log and sending it to the work order model to hold the aggregate time.
The problem is, each time I'm updating an existing log it adds the entire time to the work order instead of just the difference. So if a log was previously 12-2:00 (feeds 2 hours to WorkOrder), and you changed it to 12-1:30 it was feed an additional 1.5 hours to WorkOrder, instead of subtracting 30min
Is there a way I can check to see a time was previously sent to WorkOrder? I tried updating update_labor_hours to check if the timedelta was < or > the original time, but I couldn't really figure it out.
Any help is appreciated!
from django.utils.timezone import now
from datetime import datetime, date, timedelta
from django.db import models
from django.db.models.signals import post_save
# Create your models here.
class WorkOrder(models.Model):
labor_hours = models.DurationField(blank=True, null=True)
class WorkLog(models.Model):
work_order = models.ForeignKey(WorkOrder, on_delete=models.PROTECT)
start_time = models.TimeField(blank=True, null=True)
end_time = models.TimeField(blank=True, null=True)
def _time_spent(self):
return datetime.combine(date.today(), self.end_time) - datetime.combine(date.today(), self.start_time)
time_spent = property(_time_spent)
def update_labor_hours(sender, instance, *args, **kwargs):
instance.work_order.labor_hours = instance.work_order.labor_hours + instance.time_spent
instance.work_order.save()
post_save.connect(update_labor_hours, sender=WorkLog)

Filtering DateTime field with Date Field using Filter Set

How do I go about filtering a date time field with just a Date field.
With the model and filter below
http://localhost:8020/applications/?created=19-07-2017 returns an empty queryset even with records which have date created=19-07-2017 (The created date of the record in datetime
IN MY MODELS.PY
Class Application(models.Model):
created = models.DateTimeField(auto_now=False, auto_now_add=True)
IN MY FILTERS.PY
import django_filters
class ApplicationFilter(django_filters.FilterSet)
created = django_filters.DateTimeFilter( label='Created')
class Meta:
model = Application
fields = ['created']
Using contains works.
Use DateFilter instead and specify the date format
created=django_filters.DateFilter(input_formats=['%Y-%m-%d','%d-%m-%Y'],lookup_expr='icontains'
use contains
created = django_filters.DateTimeFilter(name='created',lookup_expr='contains')
maybe also need to change the dateformat , yyyy-mm-dd
in your filters.py write this:
import django_filters
class ApplicationFilter(django_filters.FilterSet)
class Meta:
model = Application
fields = {'created': '__all__'}
in your url :
http://localhost:8020/applications/?created__date=19-07-2017
Some of the answers below mention the use of lookup_expr='icontains'. Whilst this does work, it will yield incorrect results when the apps timezone is not UTC. This is because the date field returns the datetime stamp in UTC.
The result is that if an object has a date in UTC+2, of 2022-07-31 00:30, this will be returned as 2022-07-30 22:30, yielding incorrect results. It will be included in a filtered queryset of date 2022-07-30 and not 2022-07-31 as we expect.
Instead, we can the field name to return the date, where Django already does the conversion of the date using the specified timezone in the settings.py file. This can be done by using field_name='created__date' rather than lookup_expr='icontains' so that it is timezone aware.
created=django_filters.DateFilter(field_name='created__date')

'datetime.date' object has no attribute 'date'

This code:
import datetime
d_tomorrow = datetime.date.today() + datetime.timedelta(days=1)
class Model(models.Model):
...
timeout = models.DateTimeField(null=True, blank=True, default=d_tomorrow)
...
resuls in this error:
'datetime.date' object has no attribute 'date'
What am I doing wrong?
d_tomorrow is expected, by the Django ORM, to have a date attribute (apparently), but doesn't.
At any rate, you probably want to use a callable for the default date; otherwise, every model's default date will be "tomorrow" relative to the time the model class was initialized, not the time that the model is created. You might try this:
import datetime
def tomorrow():
return datetime.date.today() + datetime.timedelta(days=1)
class Model(models.Model):
timeout = models.DateTimeField(null=True, blank=True, default=tomorrow)
Problem solved:
from datetime import datetime, time, date, timedelta
def tomorrow():
d = date.today() + timedelta(days=1)
t = time(0, 0)
return datetime.combine(d, t)
models.DateTimeField expects the value to be datetime.datetime, not datetime.date
2015 Update:
Arrow makes this all much more straight forward.
Arrow is a Python library that offers a sensible, human-friendly approach to creating, manipulating, formatting and converting dates, times, and timestamps. It implements and updates the datetime type, plugging gaps in functionality, and provides an intelligent module API that supports many common creation scenarios. Simply put, it helps you work with dates and times with fewer imports and a lot less code.
Arrow is heavily inspired by moment.js and requests.
I had this problem when using the model from django.contrib.admin. I had two similar models, both with a date field (and both using auto_now_date=True - complete red herring); one worked, one had this error.
Turned out to be
def __unicode__(self):
return self.date
goes BANG, while this
def __unicode__(self):
return u'%s' % self.date
works just fine. Which is kind of obvious after the event, as usual.
This works for me:
import datetime
from datetime import timedelta
tomorrow = datetime.date.today() + timedelta(days=1)
class Test(models.Model):
timeout = models.DateTimeField(db_index=True, default=tomorrow)
Alternatively you could use tomorrow = datetime.datetime.now() + timedelta(days=1)
I tried out your code and it worked just fine. Can you verify that you are not modifying/redefining the import in some way?
Also try this:
import datetime as DT
d_tomorrow = DT.date.today() + DT.timedelta(days=1)
class Model(models.Model):
timeout = models.DateTimeField(null=True, blank=True, default=d_tomorrow)