Django annotate count unique user from 2 tables - django

Is it possible to do an annotate count on technically 2 different tables, but same FK?
Example:
queryset = ModelName.objects
.annotate(mileage_emp_count=Count('mileageclaim__user',distinct=True))
.annotate(general_emp_count=Count('expenseclaim__user', distinct=True))
For instance using this, is User A has a mileage and an expense claim, they will appear in both queries. So I will have result of 2 if i add them together.
What i need to do, is get a total of 1 unique user instead.
Is it possible without a lot of extra checks?

Related

Django ORM count or get precentage report

I have three models named Category, Account, and AccountCategory. I need to be able to generate a report wherein I can show the number of which each account was categorized. (e.g let's say I have 10 accounts, then I have three categories (A, B, C) I need to be able to show a piechart)
Account has a many-to-many relationship with Category and AccountCategory is the junction table.
Ideally, I need to have a result of
Name
Slug
Percentage
Num of Accounts
A
a
40%
4
B
b
10%
1
C
c
50%
5
I was able to get the raw Query but I still need to get the total number of accounts so I can get the percentage I'm struggling with how to do this on ORM.
Basically, I did query the categories, joined account categories, and did a distinct on the account so it won't return the duplicates and then just total the result. For the ORM I think I need to filter the account categories to only return the latest account category per account and then total it but I can't seem to write the exact query using ORM I tried using the Subquery and Prefetch but no avail.
you can use annotate method in django orm for this
example :
from django.db.models.functions import Concat
from django.db.models import Value
queryset = YourModel.objects.filter().annotate(percentage = Concat('count',Value('%'))).values_list('name','slug','numofaccounts', 'percentage')

Django: ValueError: Prefetch querysets cannot use raw(), values(), and values_list()

I am trying to run prefetch as below and gives me error: Prefetch querysets cannot use raw(), values(), and values_list().
queryset = SymbolList.objects.prefetch_related(
Prefetch('stock_dailypricehistory_symbol',queryset = DailyPriceHistory.objects.filter(id__in=[1,2,3,4]).values('close','volume'))).all()
DailyPriceHistory model has lot of columns, i only want close and volume
Here id__in=[1,2,3,4] is just shown for example, it can go upto 10000+ ids at a time.
You can indeed not make use of .values(…) [Django-doc] and .values_list(…) [Django-doc] when prefetching. That would also result in extra complications, since then Django has more trouble to find out how to perform the "joining" at the Django/Python level, if this is even possible.
You however do not need to use .values(…) to limit the number of columns you fetch, you can use .only(…) [Django-doc] instead. .only(…) will only fetch the given columns and the primary key immediately in memory, and will "postpone" fetching other columns. Only if you later need these columns, it will make extra queries. This is thus a bit similar how Django will only fetch the related object of a ForeignKey in memory when you need it with an extra query.
queryset = SymbolList.objects.prefetch_related(
Prefetch(
'stock_dailypricehistory_symbol',
queryset = DailyPriceHistory.objects.filter(
id__in=[1,2,3,4]
).only('close', 'volume', 'symbol_id')
)
)
The symbol_id is the column of the ForeignKey that refers from the DailyPriceHistory to the SymbolList model, this might be a different field than symbol_id. If you do not include this, Django will have to make extra queries to find out how it can link DailyPriceHistory to the corresponding SymbolList, and this will only slow down processing with extra queries, therefore you better include this as well.

Join two records from same model in django queryset

Been searching the web for a couple hours now looking for a solution but nothing quite fits what I am looking for.
I have one model (simplified):
class SimpleModel(Model):
name = CharField('Name', unique=True)
date = DateField()
amount = FloatField()
I have two dates; date_one and date_two.
I would like a single queryset with a row for each name in the Model, with each row showing:
{'name': name, 'date_one': date_one, 'date_two': date_two, 'amount_one': amount_one, 'amount_two': amount_two, 'change': amount_two - amount_one}
Reason being I would like to be able to find the rank of amount_one, amount_two, and change, using sort or filters on that single queryset.
I know I could create a list of dictionaries from two separate querysets then sort on that and get the ranks from the index values ...
but perhaps nievely I feel like there should be a DB solution using one queryset that would be faster.
union seemed promising but you cannot perform some simple operations like filter after that
I think I could perhaps split name into its own Model and generate queryset with related fields, but I'd prefer not to change the schema at this stage. Also, I only have access to sqlite.
appreciate any help!
Your current model forces you to have ONE name associated with ONE date and ONE amount. Because name is unique=True, you literally cannot have two dates associated with the same name
So if you want to be able to have several dates/amounts associated with a name, there are several ways to proceed
Idea 1: If there will only be 2 dates and 2 amounts, simply add a second date field and a second amount field
Idea 2: If there can be an infinite number of days and amounts, you'll have to change your model to reflect it, by having :
A model for your names
A model for your days and amounts, with a foreign key to your names
Idea 3: You could keep the same model and simply remove the unique constraint, but that's a recipe for mistakes
Based on your choice, you'll then have several ways of querying what you need. It depends on your final model structure. The best way to go would be to create custom model methods that query the 2 dates/amount, format an array and return it

How to limit prefetch_related data in django

I've two tables brand and a product. each brand has multiple products.
So. I used prefetch_related to get related products for a particular brand with only a minimum product price. but the problem is when I have 2 products with the same price it selects both records so how to limit this?
alternatives_data = Brand.objects.filter(category__category_slug = category_slug).prefetch_related(
Prefetch('products', queryset=Product.objects.annotate(
min_brand_price=Min('brand__products__product_price')
).filter(
product_price=F('min_brand_price')
).order_by('product_id')))
i tried everything but nothing work!
To prevent a query to return multiple records with duplicata in specific columns, use the distinct method.
In your case, add .distinct('price') to the Product queryset inside the prefetch.
There is however one caveat : It is supported on PostgreSQL only.
Documentation

Is is possible to decrease connection that made to db?

Currently, my Django application has millions of records and I want to update based on it's ManyToMany related fields value.
Consequently what I did works, but it took so many times. In order to update only three records, it uses 13 queries.
Record model has genres field which is ManyToMany field. Also, has authors field which is also ManyToMany field.
And lastly, Author model has ManyToMany field that implies genres.
for i in Record.objects.filter(authors__popular=True).only("authors", "genres"):
for a in i.authors.all():
print(a.name) # test purpose
for genre in i.genres.all():
if a.genres.exists():
a.genres.add(genre)
When i run len(connection.queries) it shows query numbers that ran, i want it to be lesser than 13.
So far i just decreased query number to 1 for 1 record. This is how i achieved
for i in Author.objects.annotate(record_count=Count('record'), record_genres=ArrayAgg('record__genres', distinct=True):
if i.record_count > 0 and i.record_genres:
i.genres.set(i.record_genres)
i.save()