count(*) as in Django Orm - django

I find this, but I need something like
select count(*) as my_count from my_table;
Its possible in Django?
Thanks.

For example if you have "Book" object just cast .count() method:
Book.objects.count()

Suppose you want to do an aggregation. Django ORM can do it. Here is a documentation.
In short, you can aggregate some count and then use it in you query. Example from documentation:
class Author(models.Model):
name = models.CharField(max_length=100)
age = models.IntegerField()
class Publisher(models.Model):
name = models.CharField(max_length=300)
num_awards = models.IntegerField()
class Book(models.Model):
name = models.CharField(max_length=300)
pages = models.IntegerField()
price = models.DecimalField(max_digits=10, decimal_places=2)
rating = models.FloatField()
authors = models.ManyToManyField(Author)
publisher = models.ForeignKey(Publisher)
pubdate = models.DateField()
class Store(models.Model):
name = models.CharField(max_length=300)
books = models.ManyToManyField(Book)
registered_users = models.PositiveIntegerField()
Now, when you do this:
>>> from django.db.models import Count
>>> pubs = Publisher.objects.annotate(num_books=Count('book'))
>>> pubs
SQL query will be the following:
SELECT "main_publisher"."id", "main_publisher"."name", "main_publisher"."num_awards", COUNT("main_book"."id") AS "num_books" FROM "main_publisher"LEFT OUTER JOIN "main_book" ON ("main_publisher"."id" = "main_book"."publisher_id") GROUP BY "main_publisher"."id", "main_publisher"."name", "main_publisher"."num_awards" LIMIT 21; args=()
And you can use aggregated data in filtering:
>>> pubs = Publisher.objects.annotate(num_books=Count('book')).filter(num_books=2)
>>> pubs
SELECT "main_publisher"."id", "main_publisher"."name", "main_publisher"."num_awards", COUNT("main_book"."id") AS "num_books" FROM "main_publisher"LEFT OUTER JOIN "main_book" ON ("main_publisher"."id" = "main_book"."publisher_id") GROUP BY "main_publisher"."id", "main_publisher"."name", "main_publisher"."num_awards" HAVING COUNT("main_book"."id") = 2 LIMIT 21; args=(2,)

Related

Problem with response values with join in django query?

i have this models.
class Product(models.Model):
id = models.IntegerField(primary_key=True)
name = models.CharField(max_length=50)
PublicationDate = models.DateField()
trend = models.IntegerField()
class User_list(models.Model):
product_id = ForeignKey(Product, on_delete=models.CASCADE)
userid = models.IntegerField()
i make a join query with select related
data = User_list.objects.select_related('product_id')
but the response don't get me Product fields value.
it's get me only User_list values, like this
"[{\"model\": \"app.user_list\", \"pk\": 1, \"fields\": {\"product_id\": 11916, \"userid\": 9}}]"
What's the problem?

Django - Query : Annotate Queryset with Related Model fields

I have following Schema in Django with PostgreSQL.
Class Person (models.Model):
name = models.CharField(max_length=255)
email= models.CharField(max_legth = 255)
created_at = models.DateTimeField()
Class PersonTask(models.Model):
person = models.ForeignKey(Person)
title = models.TextField()
created_at = models.DateTimeField()
Class PersonHistory(models.Model):
person = models.ForeignKey(Person)
note = models.TextField()
created_at = models.DateTimeField()
Now I need to query the DB like all values of Person with latest PersonTask__title as max_task and latest PersonHistory__note as max_note
Eg:
<Queryset: [
{name: "abc" ,email:"abc#gmail.com",created_at :"2019-01-02", max_task:"This is my latest tasktitle" , max_note: "This is my latest history note"},
{name: "abcd" ,email:"abcd#gmail.com",created_at :"2019-03-02", max_task:"This is my latest tasktitle for abcd" , max_note: "This is my latest history note for abcd"}
]>
But, I could max get is either id of Latest Task and Latest History by
Person.objects.filter(customer_id= 1).\
annotate( max_task = Max('persontask')).\
annotate(max_note = Max('personhistory')).\
order_by('-id')
Or a random task or note texts using below query
Person.objects.filter(customer_id= 1).\
annotate( max_task = Max('persontask__title')).\
annotate(max_note = Max('personhistory__note')).\
order_by('-id')
How this can be tackled??
As you did not mention the ForeignKeys between these models, I suspect that Task and History have FK to Person in field named person.
I would use Subquery with combination of OuterRef to tackle this query
from django.db.models import OuterRef, Subquery
result = (
Person.objects
.filter(customer_id=1)
.annotate(
task_title=Subquery(Task.objects.filter(person=OuterRef('pk')).order_by('-created_at').values('title')[:1]),
history_note=Subquery(HistoryNote.objects.filter(person=OuterRef('pk')).order_by('-created_at').values('note')[:1])
)
.order_by('-id')
)
If tasks and history are related with person you need a relationship between your models.
something like this.
class PersonTask(models.Model):
person = models.ForeignKey(Person, related_name="tasks", on_delete=models.CASCADE)
title = models.TextField()
created_at = models.DateTimeField()
class PersonHistory(models.Model):
person = models.ForeignKey(Person, related_name="histories", on_delete=models.CASCADE)
note = models.TextField()
created_at = models.DateTimeField()
And then you could get last task and last history:
person = Person.objects.get(name="name")
person.tasks.last()
person.histories.last()

Django: select data from 2 models

Good day!
I have 2 models and I am trying to get sql equivalent of : select * from both models where order=xx. Appreciate little assistance :)
class Orders(models.Model):
order_id = models.AutoField(primary_key=True)
created = models.DateTimeField(auto_now_add=True)
class ResourcePool(models.Model):
email = models.EmailField()
item_a = models.CharField()
item_b = models.CharField()
item_c = models.CharField()
order_id = models.ForeignKey(Orders)
Tried the following, but it does not inlude fields from 'Orders' model
ResourcePool.objects.filter(order_id__pk=26).values()
ResourcePool.objects.filter(order_id__pk=26).select_related().values()
ResourcePool.objects.filter(order_id__pk=26).values('orders__created','email','item_a',item_b','item_c')
try this
try this
order = Orders.objects.get(pk=26)
resource=ResourcePool.objects.filter(order_id=order.id).select_related()
And to obtain the data of "Orders"
id_order_pk26 = resource.order_id.order_id
created_pk26 = resource.order_id.created

Django Query: join a table 2 times

I have 2 tables:
Product(id, name)
Attribute(id, product_id, name, value)
How can I join the table "Attribute" 2 times when searching products? They must be in one query because of paging later.
An example: Search products which must have 2 attributes - one for name=att1, value=value1 and another for name=att2, value=value2.
Source Code:
class Product(models.Model):
product_id = models.AutoField(primary_key=True)
name = models.CharField(max_length=100, null=False)
class Attribute(models.Model):
attribute_id = models.AutoField(primary_key=True)
product = models.ForeignKey(Product, null=False)
name = models.CharField(max_length=100, null=False)
value = models.CharField(max_length=100, null=False)
A query that not working:
Product.objects.select_related().filter('attribute__name': 'n1', 'attribute__value':'v1').filter('attribute__name': 'n2', 'attribute__value':'v2')
You don't need to join them 2 times. You can create a model with ForignKey then get the set of relate attribute
For example :
you create model like this
class Product(models.Model):
name = models.CharField(max_length=100)
class Attribute(models.Model):
product = models.ForeignKey(Product)
name = models.CharField(max_length=100)
value = models.IntegerField()
You can get product item by call
item = Product.objects.get(id=xxx)
Then get all list of attribute relate to this item
from django.db.models import Q
attr = item.attribute_set.filter(Q(name='name1') | Q(name='name2'))
Use something like this:
p = Product.objects.get(pk=1)
filtered = p.attribute_set.filter(name__in=['n1','n2'],value__in=['v1','v2'])

Django getting field names from different models

Guys,
Is there an easy way to return different fields names from different models by chaining joins?
My model:
Class Item(models.Model):
item_code = models.CharField(max_length=10)
name = models.CharField(max_length=255)
...
Class Stock(models.Model):
item_code = models.ForeignKey( Item )
userid = models.ForeignKey( User )
qty = models.IntegerField()
...
I want to select " Item.Item_code, Item.name, Stock.qty where Stock.userid=2 and Item.item_code = Stock.Item_Code"
How do i do this in Django?
Gath
I want to select " Item.Item_code, Item.name, Stock.qty where Stock.userid=2 and Item.item_code = Stock.Item_Code"
You can pick these specific fields only using one SQL, provided you start from the Stock model. For instance
q = Stock.objects.select_related('userid', 'item_code').filter(
userid__id = 2).values('item_code__item_code', 'item_code__name', 'qty')
This will help if you want to limit the data and then number of queries. If you are not concerned with this then do:
q = Stock.objects.filter(userid__id = 2)
for stock in q:
print stock.item_code.item_code
print stock.item_code.name
print stock.qty
This will return a queryset with only those fields you have chose using values. You can then iterate through it.
PS: Re: your models.
Class Stock(models.Model):
item_code = models.ForeignKey( Item )
userid = models.ForeignKey( User )
qty = models.IntegerField()
...
It is a good idea to use the model name in lower case for FK relationships. For e.g. you ought to write:
Class Stock(models.Model):
item = models.ForeignKey( Item ) # Changed
user = models.ForeignKey( User ) # Changed
qty = models.IntegerField()
...
You can also use this:
Stock.objects.filter(user=2).values('item__item_code', 'item__name')
First of all change fileds names
Read this very carefuly http://docs.djangoproject.com/en/dev/ref/models/querysets/
Class Item(models.Model):
item_code = models.CharField(max_length=10)
name = models.CharField(max_length=255)
...
Class Stock(models.Model):
item = models.ForeignKey( Item )
user = models.ForeignKey( User )
qty = models.IntegerField()
...
#view
stocks = Stock.objects.filter(user=2)
for stock in stocks:
print stock.item.item_code, stock.item.name
#one query version