Django自定义唯一共同约束 [英] Django custom unique together constraint

查看:125
本文介绍了Django自定义唯一共同约束的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有一个类似下面的用户共享模型:

I have a users share model something like below:

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") )

我想为共享者(S)和接收者(R)保存一个对象(顺序与RS或SR无关)。但在unique_together以上将无法满足此要求;假设R-S在数据库中,然后如果我保存S-R,则不会对此进行验证。为此,我为共享模型编写了自定义唯一验证。

I want to save a single object for sharer(S) and receiver(R) (order doesn't matters R-S or S-R). but above unique_together will not fulfil this; Suppose R-S is in database and then if I save S-R I will not get validation for this. For this I have written custom unique validation for Share model.

    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)

此方法在正常使用中效果很好。

This method works fine in normal use.

问题:
我有一个匹配算法,该算法获取共享和接收者的请求并保存Share对象(SR或R- S),然后几乎在同一时间向他们发送响应(共享对象) 。由于我正在使用查询(没有数据库级别)检查重复项,因此需要时间,因此最后我有2个对象SR和RS。

Problem: I have an matching algorithm which gets a share's and a receiver's requests and saves Share object(either S-R or R-S) then send them response(share object) at almost same time. As I am checking duplication with query(no database level) it takes time, so at the end I have 2 Objects S-R and R-S.

我想要一些解决方案,对于共享者S和接收者RI只能保存单个共享对象,无论是SR还是RS,否则都会收到一些验证错误(例如databse的IntegrityError)。

I want some solution for this that for a sharer S and a receiver R I can only save single share object, either S-R or R-S else get some validation error(like IntegrityError of databse).

Django = 1.4, Database = Postgresql

Django=1.4, Database=Postgresql

推荐答案

您可能可以使用PostgreSQL的表达式索引但这是另一种方式:

You probably could solve this with postgresql's indexes on expressions but here is another way:

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 方法更改值,则返回ork。您还可以查看 django-denorm ,它可以通过触发器解决。

But it obviously wouldn't work if you change values with QuerySet.update method. You also could look at django-denorm, it solves this with triggers.

这篇关于Django自定义唯一共同约束的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆