繁体   English   中英

对两个单独表(Django、postgres)上的列应用唯一约束

[英]Apply unique constraint to columns on two separate tables (Django, postgres)

所以我正在建立一个有点像 github 的站点,用户和组织都可以在其中处理:

class User(AbstractUser):
    """ Using django's default user model, with its username field which looks like:

        username = models.CharField(
            _('username'),
            max_length=150,
            unique=True,
            help_text=_('Required. 150 characters or fewer. Letters, digits and @/./+/-/_ only.'),
            validators=[username_validator],
            error_messages={
                'unique': _("A user with that username already exists."),
            },
        )
    """

    # Many users to many organisations
    organisations = ManyToManyField('Organisation', related_name='users', blank=True)

class Organisation(models.Model):

    # ...other stuff, id etc
    handle = CharField(unique=True, max_length=36, null=False)

我将使用mydomain.com/username_or_handle/stuff端点设置 url。 这会产生冲突,因为用户可能与组织具有相同的句柄。

当前解决方案:

我有一个信号,在预先保存用户或组织时,它会查找两个表以确保唯一性,并在违反时引发ValidationError

@receiver(pre_save, sender=User)
@receiver(pre_save, sender=Organisation)
def check_valid_handle(sender, instance, **kwargs):
    """ The abbreviated gist...
    """
    if (Organisation.objects.filter(handle=instance.handle).count() > 0) or (User.objects.filter(username=instance.handle).count() > 0):
        raise ValidationError(detail='This handle is already taken, or prohibited. Please try another.'.format(type_str))

但严格来说,这可能会受到竞争条件的影响,因为在检查时间和模型创建/更新时间之间没有应用锁定。 此外,它感觉hacky。

是否可以在 DB 级别应用此约束,而无需从根本上改变我的模型以进行多表继承或多态性(这可能是在没有大量手术的情况下与 AbstractUser 一起工作的噩梦)? 如果是这样,如何?

多年后,我注意到这个问题有一些活动,所以想发布一个准答案。

因此,严格的答案(如评论中所示)是“不”,在您的数据库模式中执行此操作并不简单。

我走的路线

就我而言,我让Organisation派生自 django auth 的Group模型。

我还创建了一个派生自GroupUserGroup ,并与 User 有 1:1 的关系。

然后我简单地使用 Group 的name字段作为句柄,在那里有一个唯一的约束。 任务完成。

我会考虑的另一件事

当我写原始问题时,这不可用,但 django 现在有一个更 强大的约束系统,可用于在模型的创建或更新时应用此类约束。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM