Django model filter compare month fail - python

Suppose I have this model:
class User(models.Model):
id = models.AutoField(primary_key=True)
username = models.CharField(max_length=10)
last_login = models.DateTimeField(null=True)
Here is one of the records in database,
id=15,
username='yhbohh'
last_login='2015-03-31 10:57:18'
I would like to get a number count of objects with last login of month=3.
I tried in shell,
User.objects.filter(last_login__year=2015).count() # return 80
User.objects.filter(last_login__month=3).count() # return 0
User.objects.filter(last_login__day=31).count() # return 0
May I know why the last 2 queries return no records?
I have searched from the other questions and notice than someone may suggest to use date range comparison to solve this problem. But I just wanna know the root cause of this unexpected result.
Thanks a lot!

According to Django documentation:
When USE_TZ is True, datetime fields are converted to the current time
zone before filtering.

Related

Django ORM: How to group on a value and get a different value of last element in that group

I have been trying to tackle this problem all week but I just can't seem to find the solution.
Basically I want to group on 2 values (user and assignment), then take the last element based on date and get a sum of these scores. Below a description of the problem.
With Postgres this would be easily solved by using the .distinct("value") but unfortunately I do not use Postgres.
Any help would be much appreciated!!
UserAnswer
- user
- assignment
- date
- answer
- score
So I want to group on all user / assignment combinations. Then I want to get the score of each last element in that group. So basically:
user_1, assignment_1, 2019, score 1
user_1, assignment_1, 2020, score 2 <- Take this one
user_2, assignment_1, 2020, score 1
user_2, assignment_1, 2021, score 2 <- Take this one
My best attempt is using annotation but then I do not have the score value anymore:
UserAnswer.objects.filter(user=student, assignment__in=assignments)
.values("user", "assignment")
.annotate(latest_date=Max('date'))
At the end, I had to use raw query rather than django's ORM.
subquery2 = UserAnswer.objects.raw("\
SELECT id, user_id, assignment_id, score, MAX(date) AS latest_date\
FROM soforms_useranswer \
GROUP BY user_id, assignment_id\
")
# the raw queryset from above raw query
# is very similar to queryset you get from django ORM query.
# The difference is now we add 'id' and 'score' to the fields,
# so later we can retrieve them, like below.
sum2= 0
for obj in subquery2:
print(obj.score)
sum2 += obj.score
print('sum2 is')
print(sum2)
Here, I assumed that both user and assignment are foreinkeys. Something liek below:
class Assignment(models.Model):
name = models.CharField(max_length=50)
class UserAnswer(models.Model):
user = models.ForeignKey(settings.AUTH_USER_MODEL, on_delete=models.CASCADE, related_name='answers')
assignment = models.ForeignKey(Assignment, on_delete=models.CASCADE)
#assignment = models.CharField(max_length=200)
score = models.IntegerField()
date = models.DateTimeField(default=timezone.now)

Count records per day in a Django Model where date is Unix

I'm trying to create a query that counts how many queries per day there were on a certain Django table. I found a bunch of examples about it but none was dealing with Unix data. Here is what my model looks like:
class myData(models.Model):
user_id = models.IntegerField()
user = models.CharField(max_length=150)
query = models.CharField(max_length=100)
unixtime = models.IntegerField()
class Meta:
managed = False
db_table = 'myData'
So the result i'm trying to get is something like: {'27/06/2020': 10, '26/06/2020': 15 ... }
The doubt i have is: should i use a raw MYSQL query or should i use Django's ORM?
I tried to make it with a raw query, but didn't get the expected output:
select FROM_UNIXTIME(`unixtime`, '26.06.2020') as ndate,
count(id) as query_count
from myData
group by ndate
But it gave the following output:
ndate query_count
26/06/2020 1
26/06/2020 1
26/06/2020 1
26/06/2020 1
....
Can anyone help me out on this? It doesn't make the difference whether the query is made with raw mysql or Django ORM, i just need a simple way to do this
You should read up on how to use the function FROM_UNIXTIME(), specially the allowed format string options.
Your query should probably be modified to something like this:
select FROM_UNIXTIME(unixtime, '%Y/%m/%d') as ndate,
count(id) as query_count
from myData
group by ndate
Does that work for you?

Django App : Perform arithmetic operation on two fields in database and store result in third field in DB while adding data in form

I have One form in my application with different fields from which i need to subtracts value of one field from other and store result in third field on the fly in Database.
Example i have 2 fields :
1. Cost of PR Basic & 2. Cost of PO Basic
Need to calculate Delta : Cost of PO Basic - Cost of PR Basic.
Delta is also field in database table.
In models.py i have
class PR_Data(models.Model)
Cost_PR_Basic_INR = models.DecimalField(max_digits=19,decimal_places=2)
Cost_Of_PO_Basic_INR = models.DecimalField(max_digits=19,decimal_places=2)
Delta = models.DecimalField(max_digits=19,decimal_places=2, editable=True)
So how can i calculate delta from values entered in other two fields and store result in Delta field.
Thanks in advance..!!
In your views.py:
do something like this:
pr_data = PR_Data()
pr_data.Cost_PR_Basic_INR = <value1>
pr_data.Cost_Of_PO_Basic_INR = <value2>
pr_data.Delta = <value1> - <value2>
pr_data.save()
just an idea how it should work, not the complete code ;)

Django query: how to apply the mode calculation in the query?

In a previous question I was asking about how to do a complex query in Django. Here is my example model:
class Foo(models.Model):
name = models.CharField(max_length=50)
type = models.CharField(max_length=100, blank=True)
foo_value = models.CharField(max_length=14, blank=True)
time_event = models.DateTimeField(blank=True)
# ... and many many other fields
Now in my previous question #BearBrown answered me with using the When .. then expression to control my query.
Now I need something more. I need to calculate the mode (most repeated value) of the quarter of the month in the time_event field. Manually, I do it like this:
- I manually iterate over all records for the same user.
- Get the day using q['event_time'].day
- Define quarters using quarts = range(1, 31, 7)
- Then, append the calculated quarters to a list month_quarts.append(quarter if quarter <= 4 else 4)
- Then get the mode value for this specific user qm = mode(month_quarts)
Is there a way to automate this mode calculation function in the When .. then expression instead of manually iterating through all records for every user and calculating it?

GROUP BY in Django Queries

Dear StackOverFlow community:
I need your help in executing following SQL query.
select DATE(creation_date), COUNT(creation_date) from blog_article WHERE creation_date BETWEEN SYSDATE() - INTERVAL 30 DAY AND SYSDATE() GROUP BY DATE(creation_date) AND author="scott_tiger";
Here is my Django Model
class Article(models.Model):
title = models.CharField(...)
author = models.CharField(...)
creation_date = models.DateField(...)
How can I form aforementioned Django query using aggregate() and annotate() functions. I created something like this -
now = datetime.datetime.now()
date_diff = datetime.datetime.now() + datetime.timedelta(-30)
records = Article.objects.values('creation_date', Count('creation_date')).aggregate(Count('creation_date')).filter(author='scott_tiger', created_at__gt=date_diff, created_at__lte=now)
When I run this query it gives me following error -
'Count' object has no attribute 'split'
Any idea who to use it?
Delete Count('creation_date') from values and add annotate(Count('creation_date')) after filter.
Try
records = Article.objects.filter(author='scott_tiger', created_at__gt=date_diff,
created_at__lte=now).values('creation_date').aggregate(
ccd=Count('creation_date')).values('creation_date', 'ccd')
You need to use creation_date__count or customized name(ccd here) to refer the count result column, after aggregate().
Also, values() before aggregate limits group by columns and last value() declares the columns to be selected. There is no need to group by COUNT which is based on group of rows already.

Categories