D. Make
D. Make

Reputation: 600

Group objects by different models

I have two models:

class Combo(models.Model):
    price = models.DecimalField


class Choice(models.Model):
    combo = models.ForeignKey(Combo, on_delete=models.CASCADE)
    items = models.ManyToManyField(Item)

And also I have models for order:

class Order(models.Model):
    comment = models.CharField(max_length=300)


class OrderItem(models.Model):
    item = models.ForeignKey(Item, on_delete=models.CASCADE)
    amount = models.PositiveIntegerField

Combo consist of all Choices linked to Combo and to have Combo price we need to have one item for each Combo choice.
For example Combo#1 has two choices with items:

  1. Rag, Brom.
  2. Scoop.

So if our order has 2 rags, 1 broom and 2 scoop we will get 2 combos and one broom as item.

How can I split Order to combos and items to have 2 QuerySets - one for Combos and other for Inems not included to combos? Thanks!

UPD:

class Item(models.Model):
    name = models.CharField(max_length=300)
    price = models.DecimalField

Item - is a product. There are several Items for each Choice model. For example we have a Combo for fastfood with 2 Choices. Choice drink has two items - coffe and tea. Choice meal has items - chicken and hamburger. So if we buy 2 coffe and one hamburger we buy one combo (because coffe fit first choice and hamburger fit second choice) and 1 extra coffe (because there is no chicken of hamburger for it). If we had 2 coffe, 1 hamburger and 1 chicken we should split order to 2 the same combos (coffe + hamburger and coffe + chicken).

Upvotes: 0

Views: 43

Answers (1)

olinox14
olinox14

Reputation: 6672

You could go with something like this:

class Order(models.Model):
    comment = models.CharField(max_length=300)

    def get_combos(self):
        combos = []
        for combo in Combo.objects.all():
            for choice in combo.choices:
                if not any(item in self.order_items for item in choice.items):
                    break
            else:
                combos.append(combo)

        orphans = {item.name: item for item in self.order_items}
        for combo in combos:
            for choice in combo.choices:
                for item in choice.items:
                    if item.name in orphans:
                        del orphans[item.name]
                        break

        return combos, orphans

You will get two lists: combos and items not in combos (maybe you will need to arrange it a little).

If you really want to use Querysets(), you will have to transform the logic here in SQL and make a raw query, because I don't think that will be possible to achieve this with Django's basic filters...

Upvotes: 1

Related Questions