Django – 重写Model.create()方法?
Django文档只列出覆盖save()
和delete()
示例。 不过,我只想在创build模型时为我的模型定义一些额外的处理。 对于熟悉Rails的人来说,创build一个:before_create
filter是等价的。 这可能吗?
覆盖__init__()
会导致代码在对象的python表示被实例化时执行。 我不知道rails,但是:before_created
filter听起来像是在数据库中创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)
关键是这样的:
- 使用信号( 在官方文档中阅读更多)
- 使用一个好的命名空间的方法(如果它是有道理的)…我把它标记为
@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')
将不会。