7

Suppose you have a many-to-many relation in a Django model, such as:

class GroceryList(models.Model):
    items = models.ManyToManyField(GroceryItem, related_name='in_lists')

class GroceryItem(models.Model):
    name = models.CharField(unique=True)

You and me can both have the same items in two different lists, such as Avocado, and they will point to the same Avocado object.

What is the best way to implement an arbitrary order for items in each list, that can be edited separately for each list? (i.e. I have Avocado first in my list, while you have it at index 4)

django-ordered-model seems like an interesting solution, but it assumes global order across all objects.

Yuval Adam
  • 161,610
  • 92
  • 305
  • 395
  • If you use a through model, you can add a field for order to the M2M table - https://docs.djangoproject.com/en/dev/topics/db/models/#extra-fields-on-many-to-many-relationships then retrieve items from a list ordered – JamesO Nov 11 '13 at 08:35
  • Also, it seems django-ordered-model will soon have support for M2M https://github.com/bfirsh/django-ordered-model/pull/4 – Yuval Adam Nov 11 '13 at 09:58
  • You should check this answer. I found what i was looking for https://stackoverflow.com/a/10332848/11830115 – Ozan Teoman Dayanan Jun 24 '20 at 13:23

1 Answers1

14

You can use the intermediate table using through and add the ordered field in that table.

class GroceryList(models.Model):
    items = models.ManyToManyField(GroceryItem, related_name='in_lists', 
            through='Order')

class GroceryItem(models.Model):
    name = models.CharField(unique=True)

class Order(models.Model):
    number = models.PositiveIntegerField()
    gl = models.ForeignKey(GroceryList)
    gi = models.ForeignKey(GroceryItem)

So instead of doing grocerylist.items.add(groceryitem) you can do

#for groceryitem1 as 1st item in grocerylist1
Order.objects.create(gl=grocerylist1, gi=groceryitem1, number=1)

#for groceryitem1 as 10th item in grocerylist2
Order.objects.create(gl=grocerylist2, gi=groceryitem1, number=10)
Rohan
  • 52,392
  • 12
  • 90
  • 87
  • 1
    This works (Django 1.10), but it results in the admin panel being fairly useless by default. One can adapt the code from [the tutorial](https://docs.djangoproject.com/en/1.10/intro/tutorial07/#adding-related-objects) to add Inline addition of the new linking/through object. It's still not quite good if one has a lot of objects because the menu does not offer any way to search or order them. But perhaps someone can figure out a way to do that. – CoderGuy123 Aug 08 '16 at 02:18