Django 外键的唯一组合
我遇到了一种情况,我想用 unique_together
的 Meta 选项来强制执行某个规则,这里是中间模型:
class UserProfileExtension(models.Model):
extension = models.ForeignKey(Extension, unique=False)
userprofile = models.ForeignKey(UserProfile, unique=False)
user = models.ForeignKey(User, unique=False)
class Meta:
unique_together = (("userprofile", "extension"),
("user", "extension"),
# How can I enforce UserProfile's Client
# and Extension to be unique? This obviously
# doesn't work, but is this idea possible without
# creating another FK in my intermediary model
("userprofile__client", "extension"))
这是 UserProfile:
class UserProfile(models.Model):
user = models.ForeignKey(User, unique=True)
client = models.ForeignKey(Client)
谢谢。
7 个回答
13
我的解决办法是使用Django的 get_or_create 方法。通过使用这个方法,如果数据库中已经有这条记录,就会进行一次无用的获取操作;如果没有这条记录,就会创建一条新的。
举个例子:
extension = Extension.objects.get(pk=someExtensionPK)
userProfile = UserProfile.objects.get(pk=someUserProfilePK)
UserProfileExtension.objects.get_or_create(extension=extension, userprofile=userProfile)
18
我来补充一下@Wolph的回答,分享我的看法。
其实你可以自己添加验证,只需要重写validate_unique这个方法,然后把这个验证加进去就行了。
下面是一个可以用的示例代码,可能会对某些人有帮助。
from django.core.exceptions import ValidationError
class MyModel(models.Model):
fk = models.ForeignKey(AnotherModel, on_delete=models.CASCADE)
my_field = models.CharField(...) # whatever
def validate_unique(self, *args, **kwargs):
super().validate_unique(*args, **kwargs)
if self.__class__.objects.\
filter(fk=self.fk, my_field=self.my_field).\
exists():
raise ValidationError(
message='MyModel with this (fk, my_field) already exists.',
code='unique_together',
)
91
你不能这样做。
unique_together
这个设置直接对应到 SQL
中的唯一索引。也就是说,你只能在同一个表的列上设置这个,而不能在多个表的组合上设置。
不过,你可以自己添加验证,只需要重写 validate_unique
方法,然后把这个验证加进去就可以了。
文档链接:http://docs.djangoproject.com/en/dev/ref/models/instances/#django.db.models.Model.validate_unique