简体   繁体   中英

How to override how many-to-many saves on 'through' field in Django?

Summary

I want to auto-increment an order field on Item defined with m2m fields within a Set (bad name I know) so I can easily change their order. The many-to-many field is defined with a through model called SetMeta , which contains just item , set , and the new field order . I've tried over riding save() but this is never called. How can I programatically set order to something other than a default each time an item is added to set ?

Detail

Every time a new item is added to set , I want to set it's order to len(set.items.all()) . To do this, I've redefined save() on SetMeta, but it's never called. What do I have to override to ensure this works the way I'd like?

models.py

class Item(models.Model, AdminVideoMixin):
    title = models.TextField(max_length=5000)
    ....

class Set(Item):
    items = models.ManyToManyField(Item, related_name='in_sets', through='SetMeta', max_length=5000,)

    def get_absolute_url(self):
        return reverse('curate:set_detail',kwargs={'slug':self.slug})

    def get_queryset(self):
        return self.items.all().order_by('-itemOrder__order')

    def __str__(self):
        return self.title

    def auto_increment_order(self):
        print('IS THIS WORKING') <----never prints.
        length_of_set = len(self.set.items.all())
        return length_of_set

class SetMeta(models.Model):
    item = models.ForeignKey(Item, on_delete=models.CASCADE, related_name='itemOrder', max_length=5000)
    set = models.ForeignKey(Set, on_delete=models.CASCADE, related_name='SetOrder', max_length=5000)
    order = models.IntegerField(default=0, null=True,)

    def up(self):
        self.order += 1
        self.save()
        print(self.order)

    def down(self):
        self.order -= 1
        self.save()
        print(self.order)

    def save(self, *args, **kwargs):
        if self.order == 0:
            self.order = auto_increment_order(self)
        super(SetMeta, self).save(*args, **kwargs)
        print(f"{self.item.title} order is {self.order}") < ---- this never fires.

It will be fired if you create the object like this:

print(set.items.all().count())  # 

item = Item.objects.first()
set = Set.objects.first()
icount = set.items.count() + 1
SetMeta.objects.create(item=item, set=set, order=icount)

print(set.items.all().count())

Please check the documentation for more details.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM