django - 对两个单独表(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)
我将设置带有端点的 url,例如mydomain.com/username_or_handle/stuff
. 这会产生冲突,因为用户可能拥有与组织相同的句柄。
当前解决方案:
我有一个信号,在预先保存用户或组织时,会同时查找两个表以确保唯一性,并ValidationError
在违反时引发 a。
@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。
是否可以在数据库级别应用此约束,而无需从根本上更改我的模型以进行多表继承或多态性(这可能是与 AbstractUser 一起工作而无需大量手术的噩梦)?如果是这样,怎么办?
解决方案
多年后,我注意到这个问题有一些活动,所以想发布一个准答案。
所以严格的答案(如评论中出现的那样)是“不”,在您的数据库模式中执行此操作并不简单。
我走的路线
就我而言,我Organisation
是从 django auth 的Group
模型中派生出来的。
我还创建了一个UserGroup
源自Group
用户并与用户具有 1:1 关系的用户。
然后,我简单地使用name
Group 的字段作为句柄,并在那里有一个唯一的约束。任务完成。
另一件事我会考虑
这在我写原始问题时不可用,但 django 现在有一个更强大的约束系统,可用于在创建或更新模型时应用此类约束。
推荐阅读
- javascript - 为打字稿中的点亮元素组件添加事件侦听器
- firebase - 使用存储中特定文件夹的不同参数调整大小 [storage-resize-images extension]
- java - 尝试从 Android Studio 的存储中获取文本文件
- javascript - 反应JS | 应用程序无法在 IOS 和 IE/Edge 上运行
- python - pyinstaller 将 .exe 文件移动到桌面
- javascript - 对所有线程执行一次函数
- assembly - 装配 x86-16 中的模式 X,为什么平面 1 没有打印,而所有其他平面的顺序不正确?
- scala - 如何使用 scala spark 从没有标题且有超过 150 列的 csv 创建数据集
- validation - Flutter TextFormField 验证器
- netlify-cms - 将随机值返回给字段值为空的数据