【问题标题】:Django model unique together both ways两种方式都独一无二的 Django 模型
【发布时间】:2018-09-23 19:30:01
【问题描述】:

关于这个主题已经有很多问题了,但不是我要搜索的。

我有这个Model

class Options(TimeStampedModel)
    option_1 = models.CharField(max_length=64)
    option_2 = models.CharField(max_length=64)

    class Meta:
        unique_together = ('option_1', 'option_2')

现在我对字段有一个独特的约束。 有没有办法反过来定义它,这样option_1option_2 是什么并不重要

例如:

Options.create('spam', 'eggs') # Allowed
Options.create('spam', 'eggs') # Not allowed
Options.create('eggs', 'spam') # Is allowed but should not be

提前致谢!

【问题讨论】:

  • 这似乎是一件奇怪的事情,你的具体用例是什么?
  • 它们是选项..选项不应该一起出现超过一次,左或右
  • 我觉得更好的解决方案可能是多对多关系并制作一个 Option 模型。
  • 你可以通过对数据库的 CHECK 约束来做到这一点,但是你会想要更多的选项,而且会很混乱......@etene 的解决方案在这里更合适

标签: python django django-models unique-constraint


【解决方案1】:

我认为 ManyToMany 与自定义 through 表的关系和该表上的 unique_together 约束应该可以满足您的需求。

示例代码:

from django.db.models import Model, ForeignKey, ManyToManyField, CharField

class Option(Model):
    name = CharField()

class Thing(TimeStampedModel):
    options = ManyToManyField("Option", through="ThingOption")    

class ThingOption(Model):
    thing = ForeignKey(Thing)
    option = ForeignKey(Option)
    value = CharField()

    class Meta:
        unique_together = ('thing', 'option')

对于 Django 2.2+,建议使用UniqueConstraint。在文档中有一个note 说明unique_together 将来可能会被弃用。有关其用法,请参阅this 帖子。

【讨论】:

  • 谢谢!我认为这是要走的路
  • 我很难理解这一点。选项是Thing 模型上的一个字段。所以我可以在其中选择“垃圾邮件”和“鸡蛋”Option 模型? ThingOption 表如何防止选择反过来? value 是什么?
  • 这对我来说有点老了,但你可能应该阅读我链接的文档,尤其是。在多对多直通表上。 ThingOption 表不会以任何方式阻止选择,它只是阻止通过unique_together 约束为相同的Thing 多次设置相同的Option
【解决方案2】:

你可以重写 create 方法,做类似的事情

from django.db import models

class MyModelManager(models.Manager):
    def create(self, *obj_data):
        # Do some extra stuff here on the submitted data before saving...       
        # Ex- If obj_data[0]=="eggs" and obj_data[1]=="spam" is True don't allow it for your blah reason      
        # Call the super method which does the actual creation
        return super().create(*obj_data) # Python 3 syntax!!

class MyModel(models.model):
    option_1 = models.CharField(max_length=64)
    option_2 = models.CharField(max_length=64)

    objects = MyModelManager()

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2018-08-30
    • 2011-09-28
    • 1970-01-01
    • 1970-01-01
    • 2013-12-13
    • 2020-12-01
    • 2011-07-25
    • 1970-01-01
    相关资源
    最近更新 更多