Set default value for field using class method in Django

I found many similar posts on the internet on this topic, but neither state is clearly an issue.

code

class Item(models.Model):
    @classmethod
    def get_next_item_number(cls):
        return cls.objects.count() + 1

    number = models.IntegerField(default=get_next_item_number)

      

Problem

When I access the Django admin panel, the textbox associated with the "number" field contains

<classmethod object at 0x7fab049d7c50>

      

So I tried to change the code above

class Item(models.Model):
    @classmethod
    def get_next_item_number(cls):
        return cls.objects.count() + 1

    number = models.IntegerField(default=get_next_item_number())

      

but when i start django server i get:

number = models.IntegerField(default=get_next_item_number())
TypeError: 'classmethod' object is not callable

      

I know all of this could have been prevented by declaring get_next_item_number () as an external function, but this solution is not neat for me because get_next_item_number () only applies to the Item class.

Is there a solution I am missing?

+3


source to share


2 answers


I found this solution:

code



class Item(models.Model):
    @staticmethod
    def get_next_item_number():
        return Item.objects.count() + 1

    number = models.IntegerField(default=get_next_item_number.__func__)

      

I am not fully aware of the possible consequences, but it works.

+1


source


To overwrite __init__

your class method Item

and define a default value there, have a look at this code:

from django.db import models
class Item(models.Model):
    number = models.IntegerField()
    @classmethod
    def get_next_item_number(cls):
        return cls.objects.count() + 1
    def __init__(self, *args, **kwargs):
        super(Item, self).__init__(*args, **kwargs)
        if not self.pk and not self.number:
            self.number = Item.get_next_item_number()

      



And here's the output stream

>>> from your_app import models
>>> models.Item().save()
>>> models.Item().number
>>> 2
>>> models.Item().save()
>>> models.Item().number
>>> 3
>>> models.Item.objects.filter(id=1)[0].number #number only get its value from classmethod on new items
>>> 1

      

0


source







All Articles