1

I have a Posts model. And field Order = models.PositiveIntegerField() has been created for arbitrary sorting.

class Post(models.Model):
    title = models.CharField(max_length=15)
    create = models.DateTimeField(auto_now_add=True)
    Order = models.PositiveIntegerField()

Objective: in the model, overriding the save method, do add the index +1 (from the last available index of Posts) to this field when adding each new Post.

That is, each post must have an Order-index, and if there are already 3 posts on the site, then when the fourth is added - index 4 is added to his the field, and so on.

"1" index in Order field (1st post), "2" index in Order field (2nd post) etc 3, 4, 5... similar ID.

Help implement this logic im method save. It seems simple, but I don't know how to approach it.

I understand that in the model and what I do:

def save(self, *args, **kwargs):
    qs = self.order.objects.all()
    last_item = qs.latest(self.order)
    last_item.order += 1
    super().save(*args, **kwargs)

But this don't work. Help me, please!

Elliot13
  • 368
  • 2
  • 4
  • 16

1 Answers1

1

Maybe something like this:

def save(self, *args, **kwargs):
    model_class = type(self)
    last_item = model_class.objects.order_by('-order').first()
    if last_item is not None:
        self.order = last_item.order + 1

    super().save(*args, **kwargs)

You get the class (model_class), then you sort descendingly by order field and get the first instance.

I suggest you add an Index for the order field, if you don't have it already, because this field will be queried every time a new instance is created. Without indexes the performance might suffer, specially if there are many rows.

Ralf
  • 16,086
  • 4
  • 44
  • 68
  • Thanks, it's work it, but - return super(Post, self).save(*args, **kwargs) – Elliot13 Sep 30 '21 at 12:21
  • @Elliot13 the `save()` method does not return anything, so no need to use `return`; the return statement will not create problems, but it is not necessary. – Ralf Sep 30 '21 at 12:22
  • @Elliot13 and `super()` can be used without arguments, if your class structure is simple like this; it works if you pass the arguments `super(Post, self)`, but it also works without them – Ralf Sep 30 '21 at 12:23
  • Yes, you are right! Thank you! @Ralf – Elliot13 Sep 30 '21 at 12:40
  • Why `model_class = type(self)` `model_class.objects.order_by('-order').first()` not just `Post.objects.order_by('-order').first()` ??? – Elliot13 Sep 30 '21 at 14:52
  • @Elliot13 That is a preference of mine, but not strictly necessary; the `save()` method is inside the `Post` class so it already knows what class it has. This helps me to reduce errors, so if I for example change the model name to `Post2` for some reason, then I need to change less parts in the code to the new name. – Ralf Sep 30 '21 at 15:36
  • Thanks for the answer. I thought the reason was more complicated and I wanted to know. – Elliot13 Sep 30 '21 at 15:43
  • Ever heard of the [XY Problem](https://meta.stackexchange.com/questions/66377/what-is-the-xy-problem)? Don't just give OP what they want, it seems they just want an autoincrementing PK. Plus your solution is prone to race conditions. – Abdul Aziz Barkat Oct 01 '21 at 17:48