Django how to order by many to many occurences - python

let's say I have 2 models:
class Recipe(models.Model):
recipe = models.TextField()
ingredients = models.ManyToManyField(Ingredient)
class Ingredient(models.Model):
name = models.CharField()
and I want to know what ingredient is the most used in all the recipes.
How do I query that?

Read about aggregation and annotations at https://docs.djangoproject.com/en/dev/topics/db/aggregation/
To get the name of the most common ingredient:
from django.db.models import Count
most_common = Ingredient.objects.annotate(num_recipes=Count('recipe')).order_by('-num_recipes')[0]
print most_common.name

Related

how to check isSubsest in django orm

I'm using django rest framework.
and from these models, I want to get a possible cooking queryset using ingredients in fridge.
I want to get cookings that all ingredients in fridge.
How can I filter?
please help..
class Ingredient(models.Model):
name = models.CharField()
class Cooking(models.Model):
name = models.CharField()
class Fridge(models.Model):
ingredient = models.ForeignKey(Ingredient)
class CookingIngredient(models.Model):
cooking = models.ForeignKey(Cooking)
ingredient = models.ForeignKey(Ingredient)

django orm sort by foreign key occurence in another table

Suppose to have something like the following tables:
class Book(models.Model):
title = models.CharField(max_length=200)
class Purchase(models.Model):
book = models.CharField(Book, db_column="book", on_delete=models.CASCADE)
date = models.DateField()
and wanting to retrieve a queryset of books ordered by number of purchases (i.e. occurrences of the foreign key in the other table).
Book.objects.all().annotate(number_of_purchases=Count(**something**)).order_by('number_of_purchases')
Is this possible? I currently have no idea what the "something" should be replaced with.
You can work with .annotate(…) [Django-doc]:
from django.db.models import Count
Book.objects.annotate(
npurchase=Count('purchase')
).order_by('-npurchase')

Django | Aggregate Values from Foreign Key

I have two databases, A and B.
B contains a ForeignKey to A.
When I do B.objects.filter(a_id=3).values('bags').count(), I get the number I want, Y.
What is the set of commands I need in order to add this number, Y, as an annotation into database A?
Ideally, this would be an annotate type of command.
The models look like:
class A(models.Model):
name = models.CharField(max_length=150)
class B(models.Model):
name = models.CharField(max_length=150)
a_id = models.ForeignKey(A, on_delete=models.CASCADE)
bags = models.ManyToManyField(Bags)
class Bags(models.Model):
name = models.CharField(max_length=150)
Try to use b__bags lookup in annotation:
from django.db.models import Count
A.objects.annotate(bags_count=Count('b__bags'))
from django.db.models import Count
A.objects.annotate(Y=Count('b__bags'))

Django search fields in multiple models

I want to search multiple fields in many models. I don't want to use other apps like 'Haystack', only pure Django. For example:
# models.py
class Person(models.Model):
first_name = models.CharField("First name", max_length=255)
last_name = models.CharField("Last name", max_length=255)
# other fields
class Restaurant(models.Model):
restaurant_name = models.CharField("Restaurant name", max_length=255)
# other fields
class Pizza(models.Model):
pizza_name = models.CharField("Pizza name", max_length=255)
# other fields
When I type "Tonny" I should get a:
"Tonny Montana" from Person model
"Tonny's Restaurant" from Restaurant model
"Tonny's Special Pizza" from Pizza model.
One solution is to query all the models
# Look up Q objects for combining different fields in a single query
from django.db.models import Q
people = Person.objects.filter(Q(first_name__contains=query) | Q(last_name__contains=query)
restaurants = Restaurant.objects.filter(restaurant_name__contains=query)
pizzas = Pizza.objects.filter(pizza_name__contains=query)
Then combine the results, if you want
from itertools import chain
results = chain(people, restaurants, pizzas)
Ok, sure, here's a more generic solution. Search all CharFields in all models:
search_models = [] # Add your models here, in any way you find best.
search_results = []
for model in search_models:
fields = [x for x in model._meta.fields if isinstance(x, django.db.models.CharField)]
search_queries = [Q(**{x.name + "__contains" : search_query}) for x in fields]
q_object = Q()
for query in search_queries:
q_object = q_object | query
results = model.objects.filter(q_object)
search_results.append(results)
This will give you a list of all the querysets, you can then mold it to a format you choose to work with.
To get a list of models to fill search_models, you can do it manually, or use something like get_models. Read the docs for more information on how that works.

Distinct in many-to-many relation

class Order(models.Model):
...
class OrderItem(models.Model)
order = models.ForeignKey(Order)
product = models.ForeignKey(Product)
quantity = models.PositiveIntegerField()
What I need to do is to get the Order(s) which has only one order item. How can I write it using the QuerySet objects (without writing SQL)?
The easiest way to do this would be to use the Count aggregation:
from django.db.models import Count
Order.objects.annotate(count = Count('orderitem__id')).filter(count = 1)

Categories