代码之家  ›  专栏  ›  技术社区  ›  ground5hark

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

  •  61
  • ground5hark  · 技术社区  · 16 年前

    这个 Django docs save() 和 delete() . 对于熟悉Rails的人来说,这相当于创建一个 :before_create 过滤器。这可能吗?

    7 回复  |  直到 9 年前
        1
  •  175
  •   Arany Zach    8 年前

    __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)
    
        2
  •  28
  •   NeuronQ    9 年前

    我认为我们需要一个更具最佳实践的现代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. 使用信号(阅读更多 here in the official docs
    2. 使用一个好的名称空间方法(如果有意义的话)…我将它标记为 @classmethod 而不是 @staticmethod 因为很可能最终需要在代码中引用静态类成员

    如果core Django有一个实际的 post_create 信号(Imho若您需要传递一个布尔参数来更改方法的行为,那个么应该是2个方法。)

        3
  •  25
  •   nnov    7 年前

    如何创建post_保存信号的示例(从 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/

    在我看来,在这项任务中使用信号更可靠,更容易阅读,但更长。

        4
  •  22
  •   Mark Chackerian    9 年前

    从字面上回答这个问题 create

    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的方法 方法在实际创建实例之前执行一些额外的处理。

    注: 代码式

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

    将执行此修改 创造 方法,但类似于代码

    my_new_unsaved_instance = MyModel(my_field='my_field value')

    不会。

        5
  •  4
  •   Ignacio Vazquez-Abrams    16 年前

    最重要的 __init__() 将允许您在实例化模型时执行代码。别忘了打电话给家长 .

        6
  •  3
  •   Ryan Allen bradley.ayers    9 年前

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

        7
  •  1
  •   Julio Carrera    7 年前

    首选答案是正确的,但是如果您的模型是从UUIDModel派生的,那么判断是否正在创建对象的测试将不起作用。pk字段将已经有一个值。

    already_created = MyModel.objects.filter(pk=self.pk).exists()