我正在创建一个具有相同用户名和昵称的应用程序:
username = models.CharField(
max_length=40, unique=True, db_index=True)
nickname = models.CharField(max_length=100, unique=True)
但是我需要将这两个变量定义为唯一的,例如:
如果用户A具有:
username: bird
nickname: dog
和用户B尝试进行注册,例如:
username: dog
nickname: butterfly
我不会接受,因为已经使用了dog
。或者,如果用户尝试将昵称与用户名相同。
我正在考虑创建一个注册视图以手动进行此验证。但是在声明中有没有办法做到这一点?
答案 0 :(得分:0)
您可以在Meta下使用unique_together设置。
例如
class Meta:
unique_together = [[field1, field2]]
在您的情况下,这意味着鸟/狗和鸟/蝴蝶将是独特的。由于字段与鸟/狗不同,因此允许使用dod / bird,但不允许第二只鸟/狗。
答案 1 :(得分:0)
SQL通常不是为了在两列之间强制执行唯一性而设计的,所以我知道的唯一解决方案是使用split this up into two tables, one for typed names, and one for all other user information。您可以通过以下方式使答案适应模型:
class User(models.Model):
# Define fields aside from username and nickname here
class Name(models.Model):
user = models.ForeignKey('Users', on_delete=models.CASCADE)
USERNAME = 'U'
NICKNAME = 'N'
TYPE_CHOICES = (
(USERNAME, 'username'),
(NICKNAME, 'nickname')
)
type = models.CharField(max_length=1, choices=TYPE_CHOICES)
name = models.CharField(max_length=100, unique=True)
class Meta:
constraints = [
models.UniqueConstraint(fields=['user', 'type'], name='unique_user_type'),
]
# Alternative more concise, but semi-deprecated, approach:
# unique_together = [['user', 'type']]
这样做,所有名称都使用一个共享列。它有一个unique
约束,因此,用户名或昵称都不能出现两次。同样,user
和type
字段上的组合唯一性约束意味着任何给定用户只能拥有名称,用户或昵称的每个type
中的一个,而外键关系意味着您可以通过User
模型访问用户名/昵称数据,并且on_delete=models.CASCADE
设置意味着如果删除了关联的用户,则关联的名称也会被删除。
主要缺点是:
username
或nickname
;您的程序逻辑必须确保除非username
和nickname
都有效,否则永远(永久)不会创建用户话虽如此,我不鼓励这种方法。如果昵称与安全性不相关,则可以允许它们重叠(StackOverflow允许这样做;指向用户配置文件的链接是您区分其他人的方式);他们实际上根本不需要唯一。用户名显然需要唯一,但是如果昵称仅用于显示,则无需防止昵称与用户名重叠。