添加到django模型的"构造函数"

Fil*_*eia 12 django django-models

我想在创建特定django模型的实例时进行额外的初始化.我知道压倒__init__会导致麻烦.我还应该考虑其他什么选择?

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

var*_*tec 17

覆盖__init__可能有效,但这是个坏主意,而不是Django方式.

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

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

django.db.models.signals.pre_init

无论何时实例化Django模型,都会在模型__init__() 方法的开头发送此信号.

django.db.models.signals.post_init

喜欢pre_init,但是当__init__()method方法完成时会发送这个

所以你的代码应该是这样的

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)
Run Code Online (Sandbox Code Playgroud)

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

  • vartec我知道已经有一段时间了,但我刚刚碰到你的回复,我很好奇.为什么你说信号是Django的方式?为什么不在Django文档中描述的两种方法中的一种来解决这种精确的情况呢?https://docs.djangoproject.com/en/1.4/ref/models/instances/#django.db.models.Model谢谢 (7认同)
  • 上一条评论的更新链接如下:https://docs.djangoproject.com/en/1.9/ref/models/instances/ (2认同)

Eri*_*ken 7

虽然我同意通常有一种比覆盖__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

Run Code Online (Sandbox Code Playgroud)


Pab*_*ero 5

文档中建议的两种方法依赖于以任意方式创建的实例:

  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")
    
    Run Code Online (Sandbox Code Playgroud)
  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")
    
    Run Code Online (Sandbox Code Playgroud)

如果这是你的情况,我会走那条路。如果没有,我会坚持@vartec 的答案。