我有一个用户共享模型,如下所示:
class Share( models.Model ):
sharer = models.ForeignKey(User, verbose_name=_("Sharer"), related_name='sharer')
receiver = models.ForeignKey(User, verbose_name=_("Receiver"), related_name='receiver')
class Meta:
unique_together = ( ("sharer", "receiver"), ("receiver", "sharer") )
我想为sharer(S)和receiver(R)保存单个对象(顺序与R-S或S-R无关)。但以上unique_together将无法满足此要求;假设R-S在数据库中,然后如果我保存S-R,我将不会得到验证。为此,我为Share模型编写了自定义唯一验证。
def validate_unique(
self, *args, **kwargs):
super(Share, self).validate_unique(*args, **kwargs)
if self.__class__.objects.filter( Q(sharer=self.receiver, receiver=self.sharer) ).exists():
raise ValidationError(
{
NON_FIELD_ERRORS:
('Share with same sharer and receiver already exists.',)
}
)
def save(self, *args, **kwargs):
# custom unique validate
self.validate_unique()
super(Share, self).save(*args, **kwargs)
此方法在正常使用中正常工作。
问题: 我有一个匹配算法,它获取共享和接收者的请求并保存共享对象(S-R或R-S),然后几乎同时向他们发送响应(共享对象) 。因为我正在检查与查询的重复(没有数据库级别)需要时间,所以最后我有2个对象S-R和R-S。
我想要一些解决方案,对于共享者S和接收者R我只能保存单个共享对象,S-R或R-S否则会得到一些验证错误(如数据库的IntegrityError)。
Django = 1.4,Database = Postgresql
答案 0 :(得分:4)
您可能可以使用postgresql的indexes on expressions
来解决这个问题,但这是另一种方式:
class Share( models.Model ):
sharer = models.ForeignKey(User)
receiver = models.ForeignKey(User), related_name='receiver')
key = models.CharField(max_length=64, unique=True)
def save(self, *args, **kwargs):
self.key = "{}.{}".format(*sorted([self.sharer_id, self.receiver_id]))
super(Share, self).save(*args, **kwargs)
但是如果使用QuerySet.update
方法更改值,它显然不起作用。您还可以查看django-denorm,它通过触发器解决了这个问题。