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

在django model custom save()方法中,应该如何标识新对象?

  •  129
  • MikeN  · 技术社区  · 15 年前

    在保存新记录(不更新现有记录)时,我想在django模型对象的save()方法中触发一个特殊操作。

    是支票(self.id!=无)是否有必要且足以确保自我记录是新的且未被更新?有没有可能忽略的特殊情况?

    11 回复  |  直到 6 年前
        1
  •  166
  •   Dave W. Smith    7 年前
    self.pk is None:
    

    除非对象具有 UUIDField 作为其 primary_key .

    您可能需要担心的一个关键问题是,除了ID之外,字段上是否存在唯一性约束(例如,其他字段上的辅助唯一索引)。在这种情况下,您仍然可以有一个新的记录在手,但无法保存它。

        2
  •  105
  •   Artem Bernatskyi second    6 年前

    检查的替代方法 self.pk 我们可以检查 self._state 模型的

    self._state.adding is True 创建

    self._state.adding is False 更新

    我从这里得到的 page

        3
  •  42
  •   Gerry    15 年前

    检查 self.id 假定 id 是模型的主键。一种更通用的方法是使用 pk shortcut .

    is_new = self.pk is None

        4
  •  37
  •   KayEss    15 年前

    支票 self.pk == None 足以确定是否要在数据库中插入或更新对象。

    Django O/RM有一个特别讨厌的黑客,它基本上是检查pk位置是否有什么东西,如果有,则进行更新,否则进行插入(如果pk不是,则优化为插入)。

    它必须这样做的原因是,允许您在创建对象时设置pk。虽然在主键有序列列的地方并不常见,但对于其他类型的主键字段,这并不适用。

    如果您真的想知道,您必须做O/RM做的事情并在数据库中查找。

    当然,您的代码中有一个特定的案例,因此很可能 Self.Pk==无 告诉你所有你需要知道的,但它是 一个通用的解决方案。

        5
  •  8
  •   Tim Tisdall    7 年前

    您只需连接到发送“已创建”Kwargs的“保存后”信号,如果为真,则表示您的对象已插入。

    http://docs.djangoproject.com/en/stable/ref/signals/#post-save

        6
  •  6
  •   Kwaw Annor Farshid Ashouri    10 年前

    检查 self.id 以及 force_insert 旗帜。

    if not self.pk or kwargs.get('force_insert', False):
        self.created = True
    
    # call save method.
    super(self.__class__, self).save(*args, **kwargs)
    
    #Do all your post save actions in the if block.
    if getattr(self, 'created', False):
        # So something
        # Do something else
    

    这很方便,因为新创建的对象(自己)拥有它 pk 价值

        7
  •  5
  •   Jordan    9 年前

    我已经很晚了,但是当self.pk有一个与之相关联的默认值时,我遇到了一个填充self.pk的问题。

    我解决这个问题的方法是在模型中添加一个日期创建字段

    date_created = models.DateTimeField(auto_now_add=True)

    从这里你可以走了

    created = self.date_created is None

        8
  •  3
  •   yedpodtrzitko    15 年前

    宁愿用 PK 而不是 身份证件 :

    if not self.pk:
      do_something()
    
        9
  •  3
  •   metakermit    7 年前

    即使你有一个 UUIDField 作为主密钥(正如其他人所指出的那样 None 如果你只是重写 save )你可以插进姜哥的 post_save 信号。将此添加到 模特儿 :

    from django.db.models.signals import post_save
    from django.dispatch import receiver
    
    @receiver(post_save, sender=MyModel)
    def mymodel_saved(sender, instance, created, **kwargs):
        if created:
            # do extra work on your instance, e.g.
            # instance.generate_avatar()
            # instance.send_email_notification()
            pass
    

    此回调将阻止 节约 方法,这样,无论您是使用窗体还是使用django-rest框架进行Ajax调用,都可以在通过网络发送响应之前执行触发通知或进一步更新模型等操作。当然,要负责任地使用并将繁重的任务卸载到作业队列中,而不是让用户等待:)

        10
  •  1
  •   vikingosegundo    15 年前

    这是常见的方法。

    第一次保存到数据库时将给出ID

        11
  •  -3
  •   Alex L    11 年前

    要知道是更新还是插入对象(数据),请使用 self.instance.fieldname 以你的形式。在表单中定义一个clean函数,并检查当前值条目是否与前一个相同,如果不相同,则正在更新它。

    self.instance self.instance.fieldname(self.instance.fieldname) 与新值比较