重写Model.create()方法?
Django文档仅列举了覆盖save()
和delete()
示例。 不过,我只想在创建模型时为我的模型定义一些额外的处理。 对于熟悉Rails的人来说,创建一个:before_create
过滤器就相当于。 这可能吗?
覆盖__init__()
将导致代码在对象的python表示被实例化时执行。 我不知道rails,但是:before_created
过滤器听起来像它是在数据库中创建对象时要执行的代码。 如果要在数据库中创建新对象时执行代码,则应覆盖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)
一个如何创建post_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/
在我看来,使用这个任务的信号更健壮,更容易阅读,但更长。
这是旧的,有一个公认的答案,工程(Zach的),更地道一个太(迈克尔Bylstra的),但由于它仍然在谷歌的第一个结果大多数人看, 我认为我们需要一个更加最佳实践现代的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种方法。)