【问题标题】:Allow one and only one field from fields subset in Django model允许 Django 模型中的字段子集中的一个且仅一个字段
【发布时间】:2018-03-12 03:19:21
【问题描述】:

我有一个模型模型。该模型有多个属性,其中三个是:domaintldsubdomainurl - OneToOneFields。

我试图让这些字段中的一个且只有一个不为空。

我的方法有效,但我很好奇是否有更好的方法来做到这一点(我使用 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")

【问题讨论】:

    标签: django postgresql django-models model


    【解决方案1】:

    假设您的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')
    

    并废弃 saveclean 方法。现在MyModel 可以与任何模型建立关系,无论是DomainTLDSubdomain 还是URL - content_type 指向模型,object_id 保存对象 ID,content_object,这不会成为数据库中的一个字段,将用于检索对象。

    这是一种更简洁的方法,您可以摆脱那种晦涩难懂的clean 方法。 您可以进一步增强它并将content_type 的选项限制为您希望的选项。这个SO answer 解释了这一点。

    【讨论】:

      猜你喜欢
      • 2017-01-31
      • 1970-01-01
      • 2020-02-13
      • 2011-05-21
      • 1970-01-01
      • 2021-10-05
      • 2013-02-03
      • 2019-03-11
      • 1970-01-01
      相关资源
      最近更新 更多