Django docs仅列出覆盖save()
和delete()
的示例。但是,我想为我的模型定义一些额外的处理,只有在创建它们时。对于熟悉Rails的人来说,它等同于创建:before_create
过滤器。这可能吗?
答案 0 :(得分:132)
覆盖__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)
答案 1 :(得分:21)
如何创建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/
在我看来,使用这个任务的信号更健壮,更容易阅读但更长。
答案 2 :(得分:5)
要按字面意思回答问题,模型管理器中的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的方法create
方法,以便在实际创建实例之前执行一些额外的处理。
注意:代码
my_new_instance = MyModel.objects.create(my_field='my_field value')
将执行此修改后的create
方法,但代码类似
my_new_unsaved_instance = MyModel(my_field='my_field value')
不会。
答案 3 :(得分:3)
覆盖__init__()
将允许您在实例化模型时执行代码。不要忘记给父母的__init__()
打电话。
答案 4 :(得分:3)
您可以使用自定义管理器覆盖create方法,也可以在模型类上添加classmethod。 https://docs.djangoproject.com/en/1.11/ref/models/instances/#creating-objects
答案 5 :(得分:1)
首选答案是正确的,但是如果您的模型是从UUIDModel派生的,则无法判断对象是否正在创建的测试。 pk字段将已经有一个值。
在这种情况下,您可以这样做:
already_created = MyModel.objects.filter(pk=self.pk).exists()