Django query count unique NEW results per day - python

I'm keeping statistics of my app in a database in a model that looks like this
class MyStats():
event_code = django.db.models.PositiveSmallIntegerField()
timestamp = django.db.models.DateTimeField()
timestamp_date = django.db.models.DateField()
device_id = django.db.models.CharField(max_length=32)
I would like to use this data to determine, for each day, how many NEW app installations I have.
I got as far as this:
MyStats.objects.order_by('-timestamp_date').values('timestamp_date').annotate(count_total=Count('device_id', distinct=True))
But what it seems to give me is the amount of unique users per DAY, which is not desired. Any hints?

"New" really means "Occurring after x_timedelta ago":
import datetime
x_timedelta = datetime.timedelta(days=1)
x_timedelta_ago = datetime.datetime.now() - x_timedelta
your_query = MyStats.objects.filter(timestamp_date__gt=x_timedelta_ago)
your_query_distinct = your_query.order_by('-timestamp').annotate(count_total=Count('device_id', distinct=True)).values()

Related

Django filter objects F('duration') from now

I have a model:
class Examle(models.Model):
date = models.DateTime(auto_add_now=True)
duration = models.IntegerField(default=90) # days
And I want to filter it like so:
Example.objects.filter(date_lt=datetime.today() - timedelta(days=F('duration')))
Of course timedelta won't take F-object as valid parameter, but hope you got what I mean.
You can't pass F to timedelta but you can use it to make a calculation:
timedelta(days=1) * F('duration')
Alternatively, if you're on Django 2.x, try:
Example.objects.annotate(days_before_today=ExtractDay(datetime.today() - F('date'))\
.filter(days_before_today__gte=F('duration'))
Well, don't think it's the best option but in the end switched to DurationField like this:
class Examle(models.Model):
date = models.DateTime(auto_add_now=True)
duration = models.DurationField(default=timedelta(days=90)) # days
And used it like this:
Example.objects.filter(date_lt=datetime.now() - F('duration'))

Get all objects created on same day till now

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?

Compare objects from two models in Django

I have two models PriceActual and PriceBenchmark having fields date and price.
I want to compare the actual prices with the benchmark prices.
I'm not interested in benchmark prices with dates which is not present in the actual prices. So if PriceActual only has objects from the last week, I only want to query objects from PriceBenchmark also within the last week.
I guess it's something like
actual = PriceActual.objects.all()
benchmark = PriceActual.objects.filter(date__in=actual)
Edit
The models are really simple
class PriceActual(models.Model):
date = DateField()
price = DecimalField()
class PriceBenchmark(models.Model):
date = DateField()
price = DecimalField()
Maybe not the most efficient...but you could always create a list of dates:
actual = PriceActual.objects.all()
actual_dates = [x.date for x in actual]
benchmark = PriceActual.objects.filter(date__in=actual_dates)

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()

Django averaging over a date range

I have a simple uptime monitoring app built in Django which checks if a site doesn't respond to a ping request. It stores a timestamp of when it was pinged in the column "dt" and the millisecond response time in the column "ms". The site is pinged every minute and an entry is put into the database.
The Django model looks like this:
class Uptime (models.Model):
user = models.ForeignKey(User)
dt = models.DateTimeField()
ms = models.IntegerField()
I'd like to grab one day at a time from the dt column and take an average of the ms response time for that day. Even though there's 1440 entries per day I'd like to just grab the day (e.g. 4-19-2013) and get the average ms response time. The code I have been using below is undeniably wrong but I feel like I'm on the right track. How could I get this to work?
output_date = Uptime.objects.filter(user = request.user).values_list('dt', flat = True).filter(dt__range=(startTime, endTime)).order_by('dt').extra(select={'day': 'extract( day from dt )'}).values('day')
output_ms = Uptime.objects.filter(user = request.user).filter(dt__range=(startTime, endTime)).extra(select={'day': 'date( dt )'}).values('day').aggregate(Avg('ms'))
Thanks!
You need to annotate to do the group by. Django doesnt have anything in the orm for extracting only dates, so you need to add an "extra" parameter to the query, which specifies to only use the dates. You then select only those values and annotate.
Try the following:
Uptime.objects.filter(user=request.user).extra({'_date': 'Date(dt)'}).values('_date').annotate(avgMs=Avg('ms'))
This should give you a list like follows:
[{'_date': datetime.date(2012, 7, 5), 'avgMs': 300},{'_date': datetime.date(2012, 7, 6), 'avgMs': 350}]

Categories