添加到django模型的“构造函数”

时间:2012-02-23 15:08:34

标签: django django-models

我想在创建特定django模型的实例时进行额外的初始化。我知道overriding __init__ can lead to trouble。我应该考虑哪些其他选择?

更新。其他详细信息:目的是初始化该模型实例所代表的状态机。这个状态机由一个导入的库提供,它的内部状态由我的django-model持久化。我们的想法是,无论何时加载模型,状态机都将使用模型的数据自动初始化。

3 个答案:

答案 0 :(得分:16)

覆盖__init__可能会有效,但这不是一个好主意,而且不是Django方式。

在Django中执行此操作的正确方法是使用signals

在这种情况下您感兴趣的是pre_initpost_init

  

django.db.models.signals.pre_init

     

每当你实例化Django时   模型,此信号在模型__init__()的开头发送   方法

     

django.db.models.signals.post_init

     

pre_init类似,但会发送此邮件   当__init__():方法完成

所以你的代码应该是

from django.db import models
from django.db.models.signals import post_init

class MyModel(models.Model):
  # normal model definition...

def extraInitForMyModel(**kwargs):
   instance = kwargs.get('instance')
   do_whatever_you_need_with(instance)

post_init.connect(extraInitForMyModel, MyModel)

您也可以将信号连接到Django的预定义模型。

答案 1 :(得分:4)

docs中的两个建议方法依赖于以任意方式创建的实例:

  1. 在模型类上添加类方法:

    from django.db import models
    
    class Book(models.Model):
        title = models.CharField(max_length=100)
    
        @classmethod
        def create(cls, title):
            book = cls(title=title)
            # do something with the book
            return book
    
    book = Book.create("Pride and Prejudice")
    
  2. 在自定义管理器上添加方法:

    class BookManager(models.Manager):
        def create_book(self, title):
            book = self.create(title=title)
            # do something with the book
            return book
    
    class Book(models.Model):
        title = models.CharField(max_length=100)
    
        objects = BookManager()
    
    book = Book.objects.create_book("Pride and Prejudice")
    

如果那是您的情况,我会那样做。如果没有,我会坚持使用@vartec的答案。

答案 2 :(得分:0)

虽然我同意通常有比覆盖__init__更好的方法来进行您想做的事情,但有可能,并且在某些情况下它可能是有用的。

这是一个示例,该示例说明了如何正确覆盖模型的__init__方法而又不干扰Django的内部逻辑:

from django.db import models

class Book(models.Model):
    title = models.CharField(max_length=100)

    def __init__(self, *args, **kwargs):
        super().__init__(*args, **kwargs)
        # add your own logic