在Django中使用classmethod设置字段的默认值

时间:2014-09-02 11:57:59

标签: python django django-models django-admin

我在网上发现了很多关于这个主题的类似帖子,但是没有人明确说明哪个是问题。

代码

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

    number = models.IntegerField(default=get_next_item_number)

问题

当我访问Django管理面板时,与'number'字段相关的文本字段包含

<classmethod object at 0x7fab049d7c50>

所以我尝试更改上面的代码

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

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

但是当我运行django服务器时,我得到:

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

我知道通过将get_next_item_number()声明为外部函数可以防止这一切,但这个解决方案对我来说并不优雅,因为get_next_item_number()仅指Item类。

我缺少一个解决方案吗?

2 个答案:

答案 0 :(得分:2)

我找到了这个解决方案:

<强>代码

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

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

我没有完全意识到可能的后果,但它确实有效。

答案 1 :(得分:0)

覆盖__init__类的Item方法,并在那里指定默认值,看一下这段代码:

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()

这是流量输出

>>> 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