Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Ordering many-to-many relations in Django models

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.

like image 447
Yuval Adam Avatar asked Nov 11 '13 08:11

Yuval Adam


People also ask

How do you order many-to-many fields in Django?

If you use a explicitly defined through model for m2m relationship you can add your own attribute order-id . Then You can extend ManyToManyField to populate order-id per your logic on create/update and a model m2m manager that will sort the results when you fetch them by the order-id attribute.

How do you do a many-to-many relationship in Django?

To define a many-to-many relationship, use ManyToManyField . What follows are examples of operations that can be performed using the Python API facilities. You can't associate it with a Publication until it's been saved: >>> a1.


Video Answer


1 Answers

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)
like image 162
Rohan Avatar answered Sep 21 '22 06:09

Rohan