I have a model which contains date range i want to filter the data based on the range date
that is i want the data who's date range is 90 days from today's date.
class MyModel(models.Model):
name = models.CharField(max_length=255)
start_end_date = ranges.DateTimeRangeField(validators=
[validate_range_date_time])
so when we select the start date on page the end date will popoulate the same date but i cannot concatenate filter just by today date + timedelta(days=90) this is one single date and the field is date range, so how can i filter the date range data which is 90 days from now.
the model stores start_end_date as
'start_end_date': DateTimeTZRange(datetime.datetime(2022, 11, 29, 9, 15), datetime.datetime(2022, 11, 29, 10, 0),
Mymodel.objects.filter(start_end_date__contains=timezone.now() + timezone.timedelta(days=90))
timezone.now() + timezone.timedelta(days=90) = datetime.datetime(2022, 11, 29, 22, 52, 7, 759648)
the query is giving empty set
I think you could design the model more easily.
class MyModel(models.Model):
name = models.CharField(max_length=255)
start_date = models.DateTimeField()
end_date = models.DateTimeField()
Then you can find objects like the following.
target_time = timezone.now() + timezone.timedelta(days=90)
MyModel.objects.filter(start_date__lte = target_time).filter(end_date__gte = target_time)
As it's a DateTimeRangeField, I think your result can be achieved by using startswith and endswith just like that:
max_date = timezone.now() + timezone.timedelta(days=90)
MyModel.objects.filter(start_end_date__startswith__gte=timezone.now(), start_end_date__endswith__lte=max_date)
Hope it helps!
I haven't used this field myself, but in base of what i read from documentaition, it should be like this:
from psycopg2.extras import DateTimeTZRange
Mymodel.objects.filter(
start_end_date__contained_by=DateTimeTZRange(
timezone.now(),
timezone.now() + timezone.timedelta(days=90)
)
)
to check if any start_end_date field is in 90 days from now, you should also pass a datetime range.
edited:
from psycopg2.extras import DateTimeTZRange
Mymodel.objects.filter(
start_end_date__contained_by=DateTimeTZRange(
timezone.now(),
timezone.now() + timezone.timedelta(days=90),
start_end_date__lower_inc=False
)
)
Related
I do have a model as below
class Employee(models.Model):
employee_name = models.CharField(max_length=100)
joining_Date = models.DateField(blank=False, null=False)
I want to get data for last six months (including current month) joined employee count month wise.
Example:
July : 12,
June : 10,
May : 8,
April : 16,
March : 13,
February : 10,
joining_Date stores data like "2022-07-22". How to get done this by having date field?
To get the count of new employees per month you will need to annotate and use Trunc to just get the month, see below:
from datetime import date
from dateutil.relativedelta import relativedelta
from django.db.models.functions import Trunc
six_months_ago = date.today() + relativedelta(months=-6)
employees_per_month = Employee.objects.filter(join_date__gte=six_months_ago)\
.annotate(
joining_month=Trunc('joining_date', 'month', output_field=DateField())
) \
.order_by('joining_month') \
.values('joining_month') \
.annotate(employees=Count('joining_month'))
This will give you a queryset with the following structure:
<QuerySet [{'joining_month': datetime.date(2022, 6, 1), 'employees': 2},
{'joining_month': datetime.date(2022, 7, 1), 'employees': 1}, ...
Edit
To convert the QS into a flat dict:
employee_count_dict = {}
for employee_count in employees_per_month:
employee_count_dict[val['joining_month']] = val['employees']
You can try to find maximum apropriate date, and filter by it
from datetime import date
from dateutil.relativedelta import relativedelta
def find_employee(request):
today = date.today()
six_months = today - relativedelta(months=6)
emloyed_for_six_month = Employee.objects.filter(joining_Date__gte = six_months)
Your employee model should be named with a capital letter. It is conventional
https://stackoverflow.com/a/386054/14632651
i used last() to get last item of queryset after exclude some items as below:
holidays = HolidayModel.objects.all().values_list('date', flat=True)
result = BorseExchangeLog.objects.exclude(
hint_time__date__in=holidays
)
# output 1
print(list(result.valuse_list('hint_time__date',flat=True).distinct('hint_time__date')))
#output2
print(result.last().hint_time.date())
but in output2 print item that not exists in output1
i test some other codes as below:
print(list(logs.values_list('hint_time__date',flat=True).distinct('hint_time__date')))
print(list(logs.values_list('hint_time__date', flat=True).distinct('hint_time__date'))[-1])
print(logs.order_by('hint_time__date').last().hint_time.date())
[..., datetime.date(2020, 10, 21), datetime.date(2020, 10, 26)]
2020-10-26
2020-10-25
my holiday model:
class HolidayModel(models.Model):
creator = models.ForeignKey('accounts.Account', on_delete=models.PROTECT, verbose_name=_('Creator'))
reason = models.CharField(default='', max_length=200, verbose_name=_('Reason'))
date = models.DateField(default=timezone.now, verbose_name=_('Date'))
and other model is :
class BorseExchangeLog(models.Model):
create_time = models.DateTimeField(default=timezone.now)
hint_time = models.DateTimeField(default=timezone.now)
i test that by first() and problem was there too
what is problem? my code is wrong or bug from django orm?
using django2.2 and postgresql
Your datetimes are timezone aware but the date() method on datetime objects does not take the timezone into account, __date will take the timezone into account provided your DB supports it. Use the django.utils.timezone.localdate function to get a date taking into account the timezone
from django.utils.timezone import localdate
print(localdate(result.last().hint_time))
I have a dateTime field in a model. The dateTime field named breakfast_start_time takes an input.
I have to save another variable or timefield(whichever is better) named breakfast_attendence_start_time whose value should be automatically saved 15 minutes less than the breakfast_start_time.
For this we use
def save(self, *args, **kwargs):
#do something
super().save(*args, *kwargs)
I am trying to do
breakfast_attendence_start_time = breakfast_start_time - time(15,0)
but it is giving error that
class TimeField does not define '_sub_', so the '-' operator cannot be used on its instances
Edited:
Here is the full code
class Hostel(models.Model):
name = models.CharField(max_length=15)
breakfast_start_time = models.TimeField()
lunch_start_time = models.TimeField()
snacks_start_time = models.TimeField()
dinner_start_time = models.TimeField()
def save(self, *args, **kwargs):
super().save(*args, **kwargs)
I am taking start time from admin panel and I want to add 4 more variable/field like breakfast_attendence_start_time whose value should be saved automatically 15 minutes earlier than breakfast_start_time how can I achive that.
You should use timedelta to sub specific time with DateTime field. Such as
import datetime
time_before_15_minute = datetime.datetime.now() - datetime.timedelta(minutes=15)
Use DateTimeField instead of TimeField and use timedelta to make substractions
from datetime import datetime, timedelta
n = datetime(2019, 10, 4, 12, 30)
m = n - timedelta(minutes = 15) # m is now datetime(2019, 10, 4, 12, 15)
You can play with the DateTimeField but this will return time of when this function was called or used. Hope it helps
from django.utils import timezone
class AKA(models.Model):
create_time = models.DateTimeField(default=timezone.now)
def __str__(self):
return self.create_time
Is it possible to filter a models.DateTimeField but only get the month in the filter object?
The field is:
time_stamp = models.DateTimeField(
default=timezone.now)
When I filter it, this is what I get:
[datetime.datetime(2016, 9, 22, 15, 2, 48, 867473, tzinfo=),
datetime.datetime(2016, 9, 22, 15, 4, 22, 618675, tzinfo=),
datetime.datetime(2016, 9, 22, 15, 5, 20, 939593, tzinfo=)]
The filter returns 3 rows, but clearly there is too much information. I only require the months, and maybe the year.
How can I achieve this?
Any help or direction would be appreciated,
Thanks
If you are using django 1.10.x there is Extract db function
from django.db.models.functions import Extract
months = MyModel.objects.annotate(month_stamp=Extract('time_stamp', 'month')).values_list('month_stamp', flat=True)
For django 1.9.x
from django.db.models import Func
def Extract(field, date_field='DOW'):
template = "EXTRACT({} FROM %(expressions)s::timestamp)".format(date_field)
return Func(field, template=template)
months = MyModel.objects.annotate(month_stamp=Extract('time_stamp', 'month')).values_list('month_stamp', flat=True)
You can use propety:
Class your_model(models.Model):
time_stamp = models.DateTimeField(
default=timezone.now)
#property
def _get_year(self):
return self.time_stamp.strftime("%Y-%m")
year = property(_get_year) #EDIT
I have a Django model for an object with a DateField. I also have two managers that filter these objects for a specific date range.
class SchoolYearManager(models.Manager):
def get_query_set(self):
now = datetime.datetime.now()
current_year = now.year
start_date = datetime.date(current_year, 7, 1)
end_date = datetime.date((current_year + 1), 6, 30)
return super(SchoolYearManager, self).get_query_set().filter(status=self.model.LIVE).filter(event_date__range=(start_date, end_date))
class PastSchoolYearManager(models.Manager):
def get_query_set(self):
current_year = self.model.event_date.year
start_date = datetime.date(current_year, 7, 1)
end_date = datetime.date((current_year + 1), 6, 30)
return super(PastSchoolYearManager, self).get_query_set().filter(status=self.model.LIVE).filter(event_date__range=(start_date, end_date))
class Event(models.Model):
LIVE = 3
DRAFT = 4
STATUS_CHOICES = (
(LIVE, 'Live'),
(DRAFT, 'Draft'),
)
status = models.IntegerField(choices=STATUS_CHOICES, default=4, help_text="Only entries with a status of 'live' will be displayed publically.")
event_date = models.DateField()
objects = Models.Manager()
school_year_events = SchoolYearManager()
past_school_year_events = PastSchoolYearManager()
My first manager (SchoolYearManager) works as expected to return events within that date range. But when I try to do Event.past_school_year_events.all(), I get an Attribute error: "type object 'Event' has no attribute 'event_date'".
My goal with the second manager (PastSchoolYearEvents) is to wrap a generic year archive view to return events within a date range for a specific year.
Why can't I call self.model.event_date within the manager?
Am I going about this the right way? If not, what's the better way to do this?
How could this work? What event date could it be referring to? When you call Event.past_school_year_events.all(), you don't have a model instance. self.model, as the name implies, refers to the model class. So how could it know what date you mean?
I can't actually work out what it is you're trying to do - where you are going to get the date from. Do you want to start from an event, then get all the other events in the same year as that one? In which case, I suspect you just want to make past_school_year_events into a model method, not a manager.
Edit If you want to start from a specific year, a manager certainly is appropriate, but you'll need to pass the year into your manager method as a parameter. For this, I'd use a separate method on the manager, rather than overriding get_query_set - in fact, add another method to SchoolYearManager:
class SchoolYearManager(models.Manager):
def live_events(self, start_date, end_date):
return self.filter(status=self.model.LIVE).filter(event_date__range=(start_date, end_date))
def this_year(self):
now = datetime.datetime.now()
current_year = now.year
start_date = datetime.date(current_year, 7, 1)
end_date = datetime.date((current_year + 1), 6, 30)
return self.live_events(start_date, end_date)
def from_year(self, year):
start_date = datetime.date(year, 7, 1)
end_date = datetime.date(year+1, 6, 30)
return self.live_events(start_date, end_date)
Now you've got just one manager, that doesn't override get_query_set, so you don't even need to preserve the default one - you can keep this one as objects. So you can do:
Event.objects.this_year() # all this year's events
Event.objects.from_year(2010) # all events from 2010