因此,我正在整理一个类似于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。
是否有可能在数据库级别应用此约束,而无需从根本上改变我的模型来进行多表继承或多态(这可能是噩梦,而无需进行大量操作即可使用AbstractUser)?如果可以,怎么办?
答案 0 :(得分:0)
多年后,我注意到这个问题有一些活动,所以想发布一个准答案。
所以严格的答案(如评论中所示)是“不”,在您的数据库架构中执行此操作并不简单。
就我而言,我使 Organisation
派生自 django auth 的 Group
模型。
我还创建了一个 UserGroup
,它派生自 Group
并与 User 具有 1:1 的关系。
然后我简单地使用了 Group 的 name
字段作为句柄,在那里有一个唯一的约束。工作完成。
当我写原始问题时,这不可用,但 django 现在有更多的 powerful constraints system 可用于对模型的创建或更新应用此类约束。