0

I have model with field named "number". It's not the same as id, it's position while displayed on website, users can sort teams around.

I need something for default property of number. I think I should just count the number of positions in the database and add one, so if there are 15 positions inside db, the new team would be last on list and have "number" 16.

But I don't know how to do it, inside models.py file.

Inside views.py I would just use

Iteam.objects.count()

But what can I use inside model declaration? How can the model check itself?

Edit:

I tried do it as Joey Wilhelm suggested:

   from django.db import models

class ItemManager(models.Manager):

    def next_number(self):
        return self.count() + 1


class Iteam(models.Model):
    name = models.CharField()

    objects = ItemManager()
    number = models.IntegerField(default=objects.next_number())

Unfortunetly i get error:

AttributeError: 'NoneType' object has no attribute '_meta'
4
  • How are you attempting to use it? What code are you using to generate that error? It should be Iteam.objects.next_number(). Commented May 4, 2015 at 19:26
  • I try to use it exactly as in my first post. I gets this error just by running application. Where should I use this "Iteam.objects.next_number()"? Commented May 4, 2015 at 19:44
  • @Joey Forgot to mention your nick to notify. Commented May 4, 2015 at 20:01
  • Actually, mentioning like that doesn't send a notification. But, I've added an edit to my answer below which should provide an alternative which works for your scenario. Commented May 4, 2015 at 20:16

1 Answer 1

1

This is actually something you would want to do on a manager, rather than the model itself. The model should represent, and perform actions for, an individual instance. Whereas the manager represents, and performs actions for a collection of instances. So in this case you might want something like:

from django.db import models

class ItemManager(models.Manager):

    def next_number(self):
        return self.count() + 1

class Item(models.Model):
    number = models.IntegerField()

    objects = ItemManager()

That being said, I could see this leading to a lot of data integrity issues. Imagine the scenario:

  • 4 items are created, with numbers 1, 2, 3, 4
  • Item 2 gets deleted
  • 1 new item is created; this item now has a number of 4, giving you a duplicate

Edit:

The above approach will work only for pre-generating 'number', such as:

Iteam.objects.create(number=Iteam.objects.get_number(), name='foo')

In order to have it work as an actual default value for the field, you would need to use a less savory approach, such as:

from django.db import models

class Iteam(models.Model):
    name = models.CharField()
    number = models.IntegerField(default=lambda: Iteam.get_next_number())

    @classmethod
    def get_next_number(cls):
        return cls.objects.count() + 1

I would still warn against this approach, however, as it still could lead to the data integrity issues mentioned above.

Sign up to request clarification or add additional context in comments.

2 Comments

@user3667832 Item.objects.next_number()
Works perfectly now, thank you. I dont think there will be data integrity issues, because after each deletion, numbers woudl be refreshed.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.