在Django文档只列出了重写的例子save()
和delete()
。但是,我只想在模型创建时为其定义一些额外的处理。对于任何熟悉Rails的人来说,这等同于创建:before_create
过滤器。这可能吗?
在Django文档只列出了重写的例子save()
和delete()
。但是,我只想在模型创建时为其定义一些额外的处理。对于任何熟悉Rails的人来说,这等同于创建:before_create
过滤器。这可能吗?
Answers:
__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)
create
?这是一个有趣的解决方案,但是在使用Object(**kwargs).save()
或其他任何形式创建对象的情况下,该方法将无效。
super(MyModel, self).save(*args, **kwargs)
吗?
self.pk
不是检查对象是新创建还是刚更新的最佳选择。有时候你在创建的时候(定制非数据库生成的值一样提供对象ID KSUID
),它会导致这一条款从未执行...有self._state.adding
值,以确保它是否节能的第一次,或只是更新,这在这些情况下会有所帮助。
如何创建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)
这是关于最好使用信号还是自定义保存方法的深思熟虑的讨论 https://web.archive.org/web/20120815022107/http://www.martin-geber.com/thought/2007/10/29/ django-signals-vs-custom-save-method /
在我看来,将信号用于此任务更健壮,更易于阅读但更冗长。
instance.save()
。因此,在这种情况下,还会有性能损失,因为将有一个对数据库的INSERT和一个UPDATE查询。
这很古老,有一个公认的答案(Zach是有效的),也有一个比较惯用的答案(Michael Bylstra's),但是由于它仍然是大多数人在Google上看到的第一个结果,因此,我认为我们需要一种最佳做法现代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
信号,那就更干净了。(如果需要传递布尔arg来更改方法的行为,请恕我直言,应该是2个方法。)
为了从字面上回答这个问题,create
模型管理器中的方法是在Django中创建新对象的标准方法。要覆盖,请执行以下操作
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的methodcreate
方法,以在实际创建实例之前进行一些额外的处理。
注意:类似的代码
my_new_instance = MyModel.objects.create(my_field='my_field value')
将执行此修改后的create
方法,但是类似
my_new_unsaved_instance = MyModel(my_field='my_field value')
将不会。
通过覆盖,__init__()
您可以在实例化模型时执行代码。别忘了打电话给父母的__init__()
。
您可以使用自定义管理器覆盖create方法,也可以在模型类上添加类方法。https://docs.djangoproject.com/zh-CN/1.11/ref/models/instances/#creating-objects