我有一个模型模型。此模型具有多个属性,其中三个属于:domaintld
,subdomain
,url
- OneToOneField
s。
我试图让这些字段中只有一个非空。
我的方法有效,但我很好奇是否有更好的方法(我使用 PostgreSQL )。
def save(self, force_insert=False, force_update=False, using=None, update_fields=None):
self.clean()
super(Model, self).save(force_insert, force_update, using, update_fields)
def clean(self):
super(Model, self).clean()
if not(((bool(self.url) ^ bool(self.domaintld)) ^ bool(self.subdomain)) and not(self.url and self.domaintld and self.subdomain)):
raise exceptions.ValidationError("One and only one field can be used: url,domaintld,subdomain")
答案 0 :(得分:0)
假设您的models.py
:
class DomainTLD(models.Model):
# attributes and methods
class Subdomain(models.Model):
# attributes and methods
class URL(models.Model):
# attributes and methods
class MyModel(models.Model):
domaintld = models.OneToOneField(DomainTLD)
subdomain = models.OneToOneField(Subdomain)
url = models.OneToOneField(URL)
# other attributes and methods
我建议使用django contenttypes
并重构如下:
class MyModel(models.Model):
content_type = models.ForeignKey(ContentType, on_delete=models.CASCADE)
object_id = models.PositiveIntegerField()
content_object = GenericForeignKey('content_type', 'object_id')
并废弃了save
和clean
方法。现在MyModel
可以与任何模型建立关系,无论是DomainTLD
,Subdomain
还是URL
- content_type
指向模型,object_id
成立对象ID和content_object
将不会成为数据库中的字段,将用于检索对象。
这是更清洁的方式,你可以摆脱那种模糊的clean
方法。
您可以进一步增强它,并将content_type
的选项仅限于您希望的人。这个SO answer解释了这一点。