Django: Group by date over a datetime field - django

I have for example a model like this:
class Transaction(models.Model):
amount = models.FloatField()
seller = models.ForeignKey(User, related_name='sells', on_delete=models.CASCADE)
buyer = models.ForeignKey(User, related_name='purchased', on_delete=models.CASCADE)
created_at = models.DateTimeField(auto_now_add=True)
I want to group by all transactions seperated by each date and find some of them. If the created_at is of type DateField I could simply find the count on each day by this query:
Transaction.objects..values('created_at').annotate(count=Count('created_at_date')
But this doesn't work DateTimeFeilds.
My question is how can i find total count of transactions for each date for this model type.

The following will work for django 2.1 and above.
Transaction.objects.values('created_at__date').annotate(count=Count('id')).values('created_at__date', 'count').order_by('created_at__date')
You need to use __date after the name for lookup and need to put an order_by at the end.
Not sure about the previous django versions.

Related

How to inner join tables based on ManyToManyField and group by a parameter and get latest one in Django?

I have two models with ManyToManyField relationship:
class Education(models.Model):
title = models.CharField(default=None, max_length=100)
content = models.TextField(default=None)
price = models.ManyToManyField(Price)
class Price(models.Model):
cost = models.CharField(default=None, max_length=20)
created_at = models.DateTimeField(auto_now=True, null=True, blank=True)
I can fetch all rows like this:
result = Education.objects.filter(price__in=Price.objects.all()).select_related('Price')/
.values_list('title', 'content', 'price__cost', 'price__created_at')
But now i want to group by education.id and the cost parameter should be latest parameter that inserted(based on created_at).
So i want to have list of all Education with latest cost that inserted for every education.
Will it work for you, It will return the respective id
Education.objects.filter(price__in=Price.objects.all()).select_related('Price').values('id').annotate(price_id=Max('price__id'))

Querying ManyToManyTable In Django

Given the following model, I'm trying to generate a data set that will get the quantity field from OrderItems while also getting the other columns from Item and Order. I'm trying to write the query in Django's ORM but have been having issues.
class Order(models.Model):
items = models.ManyToManyField("Item", through="OrderItems")
order_date = models.DateTimeField()
class Item(models.Model):
name = models.CharField(max_length=250)
orders = models.ManyToManyField("Order", through="OrderItems")
class OrderItems(models.Model):
order = models.ForeignKey("Order", null=False, on_delete=models.CASCADE)
item = models.ForeignKey("Item", null=False, on_delete=models.CASCADE)
quantity = models.IntegerField()
The query I've tried:
Order.objects.prefetch_related('items').filter(id=order_id)
That will get me the Items for the order, but I can't figure out how to get the quantity field.
#William Thank you for your response - if you post it as the answer I'll tick it accordingly. I was missing that those objects are also available in prefetch_related.

Get the latest instance of a foreign key in django models

Hi I am facing difficulty with a query in Django ORM:
I have two models:
class Student(models.Model):
name = models.CharField(max_length=200)
created_at = models.DateTimeField(auto_now_add=True)
updated_at = models.DateTimeField(auto_now=True)
class choices:
CHOICES = {(0, "Present"),(1, "Absent")}
class Attendance(models.Model):
student = models.ForeignKey(Student, on_delete=models.CASCADE,
related_name='attendance')
date = models.DateField()
state = models.PositiveSmallIntegerField(choices=choices.CHOICES)
created_at = models.DateTimeField(auto_now_add=True)
updated_at = models.DateTimeField(auto_now=True)
I want to get all the students who were present on their respective latest dates of attendance.
I have a solution that requires three separate database queries
First get the latest Attendance id for each student and get the latest Attendance id where the status is present.
latest_attendances = Attendance.objects.order_by('student', '-date').distinct('student').values_list('id', flat=True)
latest_present_attendances = latest_attendances.filter(state=0)
Using set arithmetic we can get all the Attendance ids that are common to both (latest and "present")
set(latest_attendances) & set(latest_present_attendances)
Then pass it to a Student query
Student.objects.filter(attendance__in=set(latest_attendances) & set(latest_present_attendances))

Simple Django filter query: group by primary key?

I am running a filter query in Django with range. I thought filter always returned a queryset that was grouped by the primary key, but it seems not.
These are my models:
class MCode(models.Model):
code = models.CharField(max_length=16)
class Product(models.Model):
id = models.CharField(max_length=40, primary_key=True, db_index=True)
mcode = models.ForeignKey(MCode, null=True, blank=True, db_index=True)
class Review(models.Model):
review_id = models.CharField(max_length=32, primary_key=True, db_index=True)
product = models.ForeignKey(Product, db_index=True)
rating = models.IntegerField()
time = models.DateTimeField(db_index=True)
And this is my code:
mcode = 'M83'
base = Product.objects
tcode_obj = MCode.objects.filter(code=mcode.upper())
return base.filter(tcode=tcode_obj,
review__time__range=[date_from, date_to])
I'm getting five results, but three of them have the same primary key. It looks like I'm getting a result for each review, not each product.
Does anyone know how could I group these products by ID, and annotate with the count of the attached reviews?
When you select based on something that could match multiple times, such as Product with Reviews during a range of time, each match is added to the queryset, even if it's a duplicate of an item already there. There's actually times where you might want this behavior, but if you need to limit the queryset to just unique items, use .distinct() at the end of your query. Getting duplicates is also common when using logical ORs in your query, so be aware of times you do that and remember to use .distinct() there as well.

Ordering a Foreign Key Field by Date Added

I have the following two models:
class Position(models.Model):
position = models.CharField(max_length=100)
class UserProfile(models.Model):
user = models.ForeignKey(User, unique=True)
positions = models.ManyToManyField(Position, blank=True, null=True)
This creates a database table called userprofile_userprofile_positions, with the following three columns:
id
userprofile_id
position_id
How would I add a fourth field to this table --
created_at = models.DateTimeField(auto_now_add=True)
I would like to do this through django, if possible. Thank you.
Create a new model and specify it in the through attribute of your ManyToMany. The Django docs have a section on this exact use case: Extra fields on many-to-many relationships.