0

I have 2 models in My Django REST.

class Category(models.Model):
    name = models.CharField()

class Item(models.Model):
    name = models.CharField()
    category = models.ForeignKey(Category)

I need build queryset where i get 10 items for each category. I dont know i need Filter Category or Item, but maybe somebody can help me.

I think i need something like this: Item.objects.filter.. if item with same category not > 10.

I will be pleasure if somebody show me some way or decision.

Yura Bysaha
  • 721
  • 6
  • 17

4 Answers4

1

You can try this:

items = {}

categories = Category.objects.prefetch_related('item_set').all()
for category in categories:
    items[category.name] = list(category.item_set.all()[:10])

prefetch_related method will provide you category items without unecessary db requests.

mon io
  • 732
  • 5
  • 8
1

You can do it using id. For example, we have a category of the year. It has a lot of categories like 2014 and so on until 2022. Then we can do it like this - suppose we want to take a category from 2014-2022. 2022 is the last one, and we have it by id = 8 then do it like this:

    class Vind(models.Model):
       new_games = Games.objects.filter(date_games__lte=8, id__lt=12)

    date_games = models.ForeignKey(DateGames, on_delete=models.PROTECT)
    DateGames these are the categories of years

And now the code. We ask that date_games give us categories (there are 8 of them) less than or equal to 8 categories, and that 10 objects for each of the categories be dropped (there are 2 less).

ouflak
  • 2,458
  • 10
  • 44
  • 49
0

Very simply:

 for cat in Category.objects.all():
     if items is null:
         items = Item.objects.filter(category=cat)[:10]
     items += Item.objects.filter(category=cat)[:10]

if you want a single query, you will have to write your own custom SQL - see Select top 10 records for each category

Sina Khelil
  • 2,001
  • 1
  • 18
  • 27
  • hmmm... its not correct. I want 10 items for EACH category that i have. For example i have category 1 and 2. First category have 150 items, second 390. I want queryset which give me 10 items for each category. Yours answer give me 10 items for one category. – Yura Bysaha Nov 24 '18 at 12:52
  • I think its send to much requests to db( Maybe its possible to do only one request to db? – Yura Bysaha Nov 24 '18 at 12:58
0

Looks like if you don't have too many categories, the easiest way out would be to select all categories (or a subset of them), and then iterate over them and select 10 items from each category

items = []

categories = Category.objects.all()
for category in categories:
    items.extend(list(Item.objects.filter(category=category)[:10]))
Ibolit
  • 9,218
  • 7
  • 52
  • 96
  • Yee its easy way, but so much requests to db. – Yura Bysaha Nov 24 '18 at 12:54
  • this gets all items in categories and converts them to a list – Sina Khelil Nov 24 '18 at 12:57
  • Another way to think about it is to start from a raw sql and move towards the django query code. You get "select * from items where .... limit 10". The "limit" clause limits the whole resultset, you can't set a limit for each of the filters (in the where clause). You could do something like that with joins, but you will have to know the number of categories to make a separate join for each of them. – Ibolit Nov 24 '18 at 12:58
  • you would have to write your own custom SQL to reduce the number of queries - see https://stackoverflow.com/questions/176964/select-top-10-records-for-each-category – Sina Khelil Nov 24 '18 at 12:58
  • Thus one can try selecting the categories, and then generating the query in django iterating over them. I'll try to think about it. – Ibolit Nov 24 '18 at 13:01
  • adding `[:10]` add a limit statement - see https://docs.djangoproject.com/en/dev/topics/db/queries/#limiting-querysets – Sina Khelil Nov 24 '18 at 13:01