Sreekanth Reddy Balne
Sreekanth Reddy Balne

Reputation: 3424

Django: ManyToMany Field on a model

I have these models:

class Unit(AppModel):
    name = models.CharField(max_length=255)

    def __str__(self):
        return self.name

class Item(AppModel):
    title = models.CharField(max_length=255)
    units = models.ManyToManyField("Unit", symmetrical=False, related_name="items")

    def __str__(self):
        return self.title + self.units

class Invoice(AppModel):
    items = models.ManyToManyField("Item", symmetrical=False, related_name="invoices")

    def __str__(self):
        return "invoice_" + self.id

As you can see, we have an Item with multiple units and an Invoice with multiple items.

But, I want each item in an Invoice to have a single unit only. How to achieve that?

i.e, some_item.units should return all its type of units. Whereas, for item in some_invoice.items: return item.units should return a single unit.

Is there any other way to implement it? A new database design?? Then How? Help..

Note: I was not able to frame the title of this Post. Feel free to do so. Thanks.

Upvotes: 0

Views: 129

Answers (3)

Angela
Angela

Reputation: 1731

This is what you need I think.

class Unit(AppModel):
   name = models.CharField(max_length=255)

   def __str__(self):
      return self.name

class Item(AppModel):
    title = models.CharField(max_length=255)
    units = models.ManyToManyField("Unit", symmetrical=False, 
            related_name="items", through='ItemUnit')

    def __str__(self):
       return self.title + self.units

class ItemUnit(AppModel):
   item = models.ForeignKey(Item)
   unit = models.ForeignKey(Unit)

   def __str__(self):
     return "%s --- %s " % (self.item, self.unit)

class Invoice(AppModel):
    item_unit = models.ForeignKey(ItemUnit, blank=True, null=True, 
    related_name='invoices', on_delete=models.SET_NULL)

In the above setup, Item-Unit-Invoice is always a unique combination. Make sure you specify on_delete for the many-to-many FK.

Upvotes: 0

Aldy
Aldy

Reputation: 3102

You can change your item relation to ForeignKey

class Item(AppModel):
    title = models.CharField(max_length=255)
    units = models.ForeignKey(Unit, related_name="items")

Update

Set your invoice model between Unit and Item.

class Item(AppModel):
    units = models.ManyToManyField(Unit, through='Invoice')

class Unit(AppModel):
    ...

class Invoice(AppModel):
    item = models.ForeignKey(Item, related_name='invoice')
    unit = models.ForeignKey(Unit, related_name='invoice')

Upvotes: 0

Mikhail Burshteyn
Mikhail Burshteyn

Reputation: 5012

You need a ForeignKey to Unit on your Item model, not a ManyToManyField. That way an item will have only one unit, but a unit will be allowed to have multiple items.

Upvotes: 1

Related Questions