1

我在 django 上遇到了一个带有一组外键关系的重复键完整性错误的细微错误。

我有以下功能:

def update_relationship(actor, action, status, target):
  existing = Relation.objects.filter(actor=actor, target=target)

  # If this relation is 'on', turn it off
  if Relation.objects.filter(actor=actor, target=target, status=status):
    Relation.objects.filter(actor=actor, target=target).update(status="")
  # If this relationship is not on, turn it on
  else:
    created = True
    if existing:
      existing.update(status=status)
    else:
      Relation.objects.create(actor=actor, target=target, status=status)

如您所见,我正在测试该关系是否已存在于数据库中,如果存在则更新它,如果不存在则创建一个新行。但是,似乎在某些我无法重现的情况下,Django 给了我一个重复的键错误,即使在据我所知只有一个实例的情况下也是如此。

作为参考,这里是模型定义:

class Relation(models.Model):
  Status = Choices(('L', 'Like', 'Like'), 
                   ('D', 'Dislike', 'Dislike'), 
                   ('S', 'Save', 'Save'))
  actor     = models.ForeignKey('members.Member', related_name='relations')
  target    = models.ForeignKey('members.Member', related_name='reverse_relations')
  status    = models.CharField(choices=Status, max_length=10)
  created   = models.DateTimeField('created', auto_now_add=True)

  notified        = models.BooleanField(default=False)
  notified_mutual = models.BooleanField(default=False)

  class Meta:
    unique_together = (('actor', 'target'),)
    ordering = ('created',)
    verbose_name = 'Relation'
    verbose_name_plural = 'Relations'
4

1 回答 1

2

首先,检查是否存在的正确表达式是:

existing = Relation.objects.filter(actor=actor, target=target).exists()

但是 djano 编写句子的方法是使用get_or_create方法,这是您正在寻找的方法:

Relation.objects.get_or_create(actor=actor, target=target, 
                                 defaults={ 'status':status }
                              )

或者,对于您的情况,类似:

r, _ = Relation.objects.get_or_create(actor=actor, target=target )
r.status = '' if r.status == 'on' else status
r.save()
于 2012-07-24T17:28:58.563 回答