I have a model which contains created_at DateTimeField. I want to filter the model to get all object created on this day, month till now.
For Example : Date = 21/06/2016
Now I want to get all objects created on 21/06 till now irrespective of year.
Edit:
To be precise, I have model which stores Date of Birth of Users. I want to get all the users who were born on this day.
I tried using the __range, __gte, __month & __day. This things did not work.
Thanks for your comments and answers. I have used this answer to solve the problem. I have removed the timedelta(days) from the code.
An example of filtering outside of the queryset.
Get the date u want and remove unwanted results
from datetime import datetime, timedelta
twodaysago = str(datetime.strptime(str(datetime.now().date()-timedelta(days=2)), '%Y-%m-%d')).split()[0]
now do your query and filter it like this, you may also do it in the query filter, but if u need some extra manipulations do it in your code
date_filtered = [x for x in query\
if datetime.strptime(
x.get('created_at ', ''),
'%Y-%m-%d') > twodaysago
]
Not sure if I understand the problem correctly, but try this:
before = datetime.date(2016, 06, 21)
today = datetime.date.today()
MyModel.objects.filter(
created_at__month__range=(before.month, today.month),
created_at__day__range=(before.day, today.day)
)
From what I can understand from your question, you want to get all objects with the same date as today, irrespective of the year.
I would use something like this. See if this helps.
from datetime import datetime
today = datetime.now()
OneModel.objects.filter(created_at__day = today.day.__str__(),
created_at__month = today.month.__str__())
For more see this link: How can I filter a date of a DateTimeField in Django?
Related
I'm currently using the filter "created_at__range" to specify the first and last day of the month, but this code doesn't reflect the data registered today.
this_month = datetime.datetime.today()
first_day = datetime.datetime(this_month.year, this_month.month, 1)
this_month = this_month.strftime('%Y-%m-%d')
first_day = first_day.strftime('%Y-%m-%d')
time = obj.filter(created_at__range=(first_day, this_month)).aggregate(
time=Sum('time'))['time']
Currently, I'm using timedelta(days=1) to add a day, but if I do this, for example, if the date is 3/31, it will be 4/1 and the tally will be wrong.
this_month = datetime.datetime.today() + timedelta(days=1)
Why is this happening?
If anyone knows how to improve it, I'd appreciate it if you could let me know.
I assume that your field created_at is a DateTimeField. Quoting the warning from Django's documentation
Warning
Filtering a DateTimeField with dates won’t include items on the
last day, because the bounds are interpreted as “0am on the given
date”. If pub_date was a DateTimeField, the above expression
would be turned into this SQL:
SELECT ... WHERE pub_date BETWEEN '2005-01-01 00:00:00' and '2005-03-31 00:00:00';
Generally speaking, you can’t mix dates and datetimes.
I would like to add why even convert the datetime to a string simply use the object in your query:
this_month = datetime.datetime.today()
first_day = datetime.datetime(this_month.year, this_month.month, 1)
time = obj.filter(
created_at__range=(first_day, this_month)
).aggregate(time=Sum('time'))['time']
Edit: In fact to make this a little easier for yourself and if there is no object that would have a datetime in the future, just let the ORM and database do a little more work if needed by just comparing the day and the year:
today = datetime.datetime.today()
time = obj.filter(
created_at__year=today.year,
created_at__month=today.month,
).aggregate(time=Sum('time'))['time']
I have a table with a set of Orders that my customers made (purchased, to say so).
The customers can choose the delivery date. That value is stored in each Order in a field called Order.delivery_date (not too much inventive there)
class Order(BaseModel):
customer = ForeignKey(Customer, on_delete=CASCADE, related_name='orders')
delivery_date = DateField(null=True, blank=True)
I would like to annotate a queryset that fetches Orders with the previous Sunday for that delivery_date (mostly to create a weekly report, "bucketized" per week)
I thought "Oh! I know! I'll get the date index in the week and I'll subtract a datetime.timedelta with the number of days of that week index, and I'll use that to get the Sunday (like Python's .weekday() function)":
from server.models import *
import datetime
from django.db.models import F, DateField, ExpressionWrapper
from django.db.models.functions import ExtractWeekDay
Order.objects.filter(
delivery_date__isnull=False
).annotate(
sunday=ExpressionWrapper(
F('delivery_date') - datetime.timedelta(days=ExtractWeekDay(F('delivery_date')) + 1),
output_field=DateField()
)
).last().sunday
But if I do that, I get a TypeError: unsupported type for timedelta days component: CombinedExpression when trying to "construct": the timedelta expression.
Not using the F function in the Extract doesn't make a difference either: I get the same error regardless of whether I use Extract(F('delivery_date')) or Extract('delivery_date')
This is a Python 3.4, with Django 2.0.3 over MySQL 5.7.21
I know that I can always fetch the Order object and do this in Python (I even have a little helper function that would do this) but it'd be nice to fetch the objects with that annotation from the DB (and also for learning purposes)
Thank you in advance.
Oh, I had forgotten about extra
It looks like this should do (at least for MySQL)
orders_q = Order.objects.filter(
delivery_date__isnull=False
).extra(
select={
'sunday': "DATE_ADD(`delivery_date`, interval(1 - DAYOFWEEK(`delivery_date`)) DAY)"
},
).order_by('-id')
It seems to work:
for record in orders_q.values('sunday', 'delivery_date'):
print("date: {delivery_date}, sunday: {sunday} is_sunday?: {is_sunday}".format(
is_sunday=record['sunday'].weekday() == 6, **record)
)
date: 2018-06-04, sunday: 2018-06-03 is_sunday?: True
date: 2018-05-30, sunday: 2018-05-27 is_sunday?: True
date: 2018-05-21, sunday: 2018-05-20 is_sunday?: True
date: 2018-06-04, sunday: 2018-06-03 is_sunday?: True
EDIT: Apparently, extra is on its way to being deprecated/unsupported. At the very least, is not very... erm... fondly received by Django developers. Maybe it'd be better using RawSQL instead. Actually, I was having issues trying to do further filter in the sunday annotation using extra which I'm not getting with the RawSQL method..
This seems to work better:
orders_q = orders_q.annotate(
sunday=RawSQL("DATE_ADD(`delivery_date`, interval(1 - DAYOFWEEK(`delivery_date`)) DAY)", ())
)
Which allows me to further annotate...
orders_q.annotate(sunday_count=Count('sunday'))
I'm not sure why, but when I was using extra, I'd get Cannot resolve keyword 'sunday' into field
My queryset filter did return the correct filtered data on the first date that I wrote the code but after that the date is stuck to that specific date and does not bring up the filtered information based on the current date.
What am I doing wrong?
today = datetime.date.today()
todaydate = today
url(r'^maanta/', ListView.as_view(
queryset= Article.objects.filter(pub_date__startswith=todaydate),
template_name="myarticle.html")),
If you assign the date like you did on the module level, it is only evaluated once.
The trick is to use a lambda function:
todaydate = lambda: datetime.date.today()
And to adjust your lookup to:
Article.objects.filter(pub_date__startswith=todaydate())
I want to write a test, that takes a time from a saved object recipient.expiry_date and checks that the date is 30 days in the future.
This is what I have tried:
days_to_match = timezone.now() + timedelta(days=30)
self.assertEqual(recipient.expiry_date, days_to_match)
Because it also contains the time this won't match.
How can this be done?
Please note that recipient.expiry_date is set in my model using timezone.now()so comparison on dates from python seemed to error.
As you can see in this SO answer, you can use the date() to compare only the date and not the time. Or you can put the time data = 0.
self.assertEqual(recipient.expiry_date.date(), days_to_match.date())
You can just look at the date portions:
self.assertEqual(recipient.expiry_date.year, days_to_match.year)
self.assertEqual(recipient.expiry_date.month, days_to_match.month)
self.assertEqual(recipient.expiry_date.day, days_to_match.day)
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()