How to update exisiting date field in django using existing days field? - python

I want to update existing date field in django using existing days field in the same table.
For example
class Sample(models.Model):
notify_status = models.BooleanField(default=0)
next_date = models.DateField(blank=True, null=True)
days = models.IntegerField(blank=True, null=True)
Now I want to add days to next_date where next_date is less than todays date.
I have tried this:
import datetime
from django.db.models import F
Sample.objects.filter(next_date__lt=today).update(next_date=F('next_date')+datetime.timedelta(days=F('days')))
But its not working.
Here is the output
Something went wrong in period_retrack.py: unsupported type for timedelta days component: F
Expected Output
I want next_date to be increased by the number of days in the same table for every row where next_date is less than current_date i.e, today's date

You can cast the days field value to an interval at the database level:
import datetime
from django.db.models import CharField, DurationField, F, Value
from django.db.models.functions import Cast, Concat
Sample.objects.filter(next_date__lt=today).update(
next_date=F("next_date")
+ Cast(
Concat("days", Value(" days"), output_field=CharField()),
output_field=DurationField(),
)
)
Notice that I'm doing the cast in 2 steps:
Concatenate the value with the " days" suffix (e.g. "1 days")
Cast this string to a duration
This would work with Postgres, I'm not sure about other databases.

Related

MongoEngine filter for date column

I am trying to use MongoEngine to apply a filter on a mongodb collection called Employees. The filter is based on country, city and join_date.
The filter condition is that the number of months obtained by subtracting join_date from today's date should be a minimum of "x" months, where x is a setting value. So, for example, if x is 18 months, I need to find all employees whose join_date was a minimum of 18 months prior to today's date.
I am trying to achieve this by calling the filter() method, but I'm unable to figure out how to do that.
matching_records = Employees.objects(
country=rule.country,
city=rule.city) \
.filter(relativedelta.relativedelta(datetime.datetime.now, join_date).months > 18)
I get an error, "name join_date is not defined". I am unable to figure out how to get the filter to work. Please help.
You need to use the lte (less than or equal) or gte (greater than or equal) operators like this:
from datetime import datetime, timedelta
import dateutil.relativedelta
from mongoengine import *
connect()
now = datetime.utcnow()
yesterday = now - dateutil.relativedelta.relativedelta(days=5)
past = now - dateutil.relativedelta.relativedelta(months=20)
class TestDate(Document):
dt = DateTimeField()
# Saving 3 objects to verify the query works
TestDate(dt=now).save()
TestDate(dt=yesterday).save()
TestDate(dt=past).save()
TestDate.objects(dt__lte=now - dateutil.relativedelta.relativedelta(months=18)) # return TestData associated with `past`
TestDate.objects(dt__gte=now - dateutil.relativedelta.relativedelta(months=18)) # return TestData associated with `now` and `yesterday`

How to get the number of days by subtraction from the datetime field and then filter in Django?

This is model:
class Work(models.Model):
start_date = DateTimeField()
end_date = DateTimeField()
sot = IntegerField(help_text='days')
I want to subtract the start time from the end time to get the number of days to compare with sot and filter out the data I want.
I can get what I want through the loop, but this is very inelegant, is there any way to do it through ORM?
[w for w in Work.objects.all() if (w.end_date - w.start_date).days < w.sot ]
You can use F expiression
Use F to reference field end_date and start_date
Subtract start_date from end_date, which give a timestamp difference in microseconds.
Convert the timestamp difference in microseconds to days
Filter the day difference with sot field
Work.objects.filter(sot__gt=(F('end_date')-F('start_date'))/(3600*24*1000*1000))

django extract only year from date time in queryset

I have a purchases table with a column datatime. I would like to select all purchases I have done in the current year. bellow is my code but is not working!
import datetime
today = datetime.date.today()
year = Purchases.objects.filter(date__year = today.year)
I expect the year should be 2018 extracted from 2018-04-12
You can use ExtractYear function, here is example:
from django.db.models.functions import ExtractYear
qs = Purchases.objects.annotate(year=ExtractYear('date')).filter(year = today.year)
While querying, we can get year from model field of type DateField as fieldname__year (for comparision). If we have a field named 'purchase_date' in our model, we can filter data for a particular year as:
MyModel.objects.filter(purchase_date__year=targetyear)
In your case, if the column name is datatime. You can get the purchases done in current year as:
import datetime
today = datetime.date.today()
purchases = Purchases.objects.filter(datatime__year=today.year)

Django: Filter objects by date range

My object model is :
class Event(models.Model):
start = models.DateTimeField()
end = models.DateTimeField()
I need to filter all objects for today.
I have one object with start date 2014/03/01 00:00 and end date 2014/10/01 00:00.
I need to have this object when filtering objects by today date ex.:
Event.objects.filter(start__gte=today, end__lte=today)
How can I filter objects by today date and get all results where start > today < end ?
Get the today's date from datetime.date.today() and use gt and lt:
import datetime
today = datetime.date.today()
Event.objects.filter(start__lt=today, end__gt=today)
This would filter objects where start date is less than today and end date is greater than today.
You can use combine method of datetime module:
import datetime
today = datetime.datetime.today()
Event.objects.filter(start__gte=datetime.datetime.combine(today, datetime.time.min),
end__lte=datetime.datetime.combine(today, datetime.time.max))

Django Group By Weekday?

I'm using Django 1.5.1, Python 3.3.x, and can't use raw queries for this.
Is there a way to get a QuerySet grouped by weekday, for a QuerySet that uses a date __range filter? I'm trying to group results by weekday, for a query that ranges between any two dates (could be as much as a year apart). I know how to get rows that match a weekday, but that would require pounding the DB with 7 queries just to find out the data for each weekday.
I've been trying to figure this out for a couple hours by trying different tweaks with the __week_day filter, but nothing's working. Even Googling doesn't help, which makes me wonder if this is even possible. Any Django guru's here know how, if it is possible to do?
Since extra is deprecated, here is a new way of grouping on the day of the week using ExtractDayOfWeek.
from django.db.models.functions import ExtractWeekDay
YourObjects.objects
.annotate(weekday=ExtractWeekDay('timestamp'))
.values('weekday')
.annotate(count=Count('id'))
.values('weekday', 'count')
This will return a result like:
[{'weekday': 1, 'count': 534}, {'weekday': 2, 'count': 574},.......}
It is also important to note that 1 = Sunday and Saturday = 7
Well man I did an algorithm this one brings you all the records since the beginning of the week (Monday) until today
for example if you have a model like this in your app:
from django.db import models
class x(models.Model):
date = models.DateField()
from datetime import datetime
from myapp.models import x
start_date = datetime.date(datetime.now())
week = start_date.isocalendar()[1]
day_week =start_date.isoweekday()
days_quited = 0
less_days = day_week
while less_days != 1:
days_quited += 1
less_days -= 1
week_begin = datetime.date(datetime(start_date.year,start_date.month,start_date.day-days_quited))
records = x.objects.filter(date__range=(week_begin, datetime.date(datetime.now())))
And if you add some records in the admin with a range between June 17 (Monday) and June 22 (today) you will see all those records, and if you add more records with the date of tomorrow for example or with the date of the next Monday you will not see those records.
If you want the records of other week unntil now you only have to put this:
start_date = datetime.date(datetime(year, month, day))
records = x.objects.filter(date__range=(week_begin, datetime.date(datetime.now())))
Hope this helps! :D
You need to add an extra weekday field to the selection, then group by that in the sum or average aggregation. Note that this becomes a database specific query, because the 'extra' notation becomes passed through to the DB select statement.
Given the model:
class x(models.Model):
date = models.DateField()
value = models.FloatField()
Then, for mysql, with a mapping of the ODBC weekday to the python datetime weekday:
x.objects.extra(select={'weekday':"MOD(dayofweek(date)+5,7)"}).values('weekday').annotate(weekday_value=Avg('value'), weekday_value_std=StdDev('value'))
Note that if you do not need to convert the MySql ODBC weekday (1 = Sunday, 2 = Monday...) to python weekday (Monday is 0 and Sunday is 6), then you do not need to do the modulo.
For model like this:
class A(models.Model):
date = models.DateField()
value = models.FloatField()
You can use query:
weekday = {"w": """strftime('%%w', date)"""}
qs = A.objects.extra(select=weekday).values('w').annotate(stat = Sum("value")).order_by()

Categories