Django – 重写Model.create()方法?

Django文档只列出覆盖save()delete()示例。 不过,我只想在创build模型为我的模型定义一些额外的处理。 对于熟悉Rails的人来说,创build一个:before_createfilter是等价的。 这可能吗?

覆盖__init__()会导致代码在对象的python表示被实例化时执行。 我不知道rails,但是:before_createdfilter听起来像是在数据库中创build对象时要执行的代码。 如果要在数据库中创build新对象时执行代码,则应覆盖save() ,检查对象是否具有pk属性。 代码看起来像这样:

 def save(self, *args, **kwargs): if not self.pk: # This code only happens if the objects is # not in the database yet. Otherwise it would # have pk super(MyModel, self).save(args, kwargs) 

一个如何创buildpost_save信号的例子(来自http://djangosnippets.org/snippets/500/

 from django.db.models.signals import post_save from django.dispatch import receiver @receiver(post_save, sender=User) def create_profile(sender, instance, created, **kwargs): """Create a matching profile whenever a user object is created.""" if created: profile, new = UserProfile.objects.get_or_create(user=instance) 

这里是一个深思熟虑的讨论是否最好使用信号或自定义保存方法http://www.martin-geber.com/thought/2007/10/29/django-signals-vs-custom-save-method/

在我看来,使用这个任务的信号更健壮,更容易阅读,但更长。

覆盖__init__()将允许您在模型实例化时执行代码。 不要忘记调用父母的__init__()

您可以使用自定义pipe理器覆盖create方法,也可以在模型类上添加classmethod。 https://docs.djangoproject.com/en/1.11/ref/models/instances/#creating-objects

这个很老,有一个可以接受的答案(Zach's),还有一个比较习惯的答案(Michael Bylstra's),但是由于它仍然是谷歌大多数人看到的第一个结果, 所以我认为我们需要一个更好的现代Django样式答案在这里

 from django.db.models.signals import post_save class MyModel(models.Model): # ... @classmethod def post_create(cls, sender, instance, created, *args, **kwargs): if not created: return # ...what needs to happen on create post_save.connect(MyModel.post_create, sender=MyModel) 

关键是这样的:

  1. 使用信号( 在官方文档中阅读更多)
  2. 使用一个好的命名空间的方法(如果它是有道理的)…我把它标记为@classmethod而不是@staticmethod因为很可能你最终需要在代码中引用静态类成员

如果核心Django将有一个实际的post_create信号,即使更清洁。 (Imho如果你需要传递一个布尔参数来改变一个方法的行为,那应该是2个方法。)

要从字面上回答这个问题,模型pipe理器中的create方法是在Django中创build新对象的标准方法。 重写,做类似的事情

 from django.db import models class MyModelManager(models.Manager): def create(self, **obj_data): # Do some extra stuff here on the submitted data before saving... # For example... obj_data['my_field'] = my_computed_value(obj_data['my_other_field']) # Now call the super method which does the actual creation return super().create(**obj_data) # Python 3 syntax!! class MyModel(models.model): # An example model my_field = models.CharField(max_length=250) my_other_field = models.CharField(max_length=250) objects = MyModelManager() 

在这个例子中,我重写了Manager的方法create方法,在实际创build实例之前做一些额外的处理。

注意:类似的代码

my_new_instance = MyModel.objects.create(my_field='my_field value')

会执行这个修改后的create方法,但是代码就像

my_new_unsaved_instance = MyModel(my_field='my_field value')

将不会。