django自定义字段「sql唯一值约束」
我之前介绍过使用Django的CheckConstraint类来验证带有choices的字段和总和为100%的百分比字段。这里是另一个用例。
我最近在做的一个项目要存储“分数”,它可能只有一个单个的输入值:一个整数、一个小数或一个时间段(duration)。因为它们具有不同的类型,所以它们被存储在数据库中的不同列中。因此,对于单个分数,只能填充这些列中的一列(不为空)。
你可以通过使用模型继承来解决这个问题。这样做的缺点是,无论是使用具体继承还是抽象继承,你都会需要多个表。对于单个不同的字段来说,这也是大量的工作。
我们没有这样做,而是采用了具有多个值列的单一模型方法,我们只需要设置其中一个值列。这个模型看起来像这样:
(IntegerChoices是Django 3.0新枚举类型的一种)
如果type是 ScoreType.POINTS,则value_points列应该被设置。同样,如果type是ScoreType.DURATION,则value_duration列应该被设置。
尽管你对我们的Python代码满足这个约束充满自信,除非你让数据库强制执行它,否则一个错误就可能打破这个假设。例如,你可能不小心写了这样一个查询:
(将 datetime导入为dt.)
如此糟糕的数据可能会产生各种意想不到的后果。如果你发现这样的糟糕数据已经被创建了一段时间,它可能需要很长时间才能解开。如果可以的话,最好尽早预防!
为此,你可以添加一个CheckConstraint来强制保证填充值列与type相匹配。它看起来是这样的:
约束是使用Q对象定义的,Q对象会接受与filter相同的参数来限制这些情况。在这里,我们实际上列出了这两种有效的情况,并使用Python的按位或运算符|对它们进行或运算。由于Python中的限制,Q不能对此使用普通的or运算符。
在makemigrations并应用此迁移之后,你可以测试该约束。你可以创建刚好合法的Score实例:
但是如果你尝试保存错误的数据, 你将得到一个 IntegrityError:
运行的很好。
你还可以将该约束与代理模型结合使用,以根据类型划分Score。我还没有完全尝试这一点,但是它看起来像多表继承的一个可行的替代方法。你甚至可以添加一个助手函数来自动生成类。
你可以像这样完成一个没有任何自动生成的简单的“Points”实现:
DURATION实现只需要一点复制-粘贴-替换即可。
这个实现使用一个自定义管理器来只返回正确类型的实例。并且它还覆盖了__init__ 来强制保证type。我确信我们还可以添加一些其他的方法来使其更加流畅,但是你已经了解了其中的思想。
结语有关本文中使用的示例项目的源代码,包括该检查约束的一个额外的自动生成工具,请在GitHub上查看。(地址:https://github.com/adamchainz/django-demo-constraint-single-column-not-/blob/master/example/core/models.py )
希望这篇文章能帮助你提升你的CheckConstraint应用,
—Adam
英文原文:https://adamj.eu/tech/2020/03/25/django-check-constraints-one-field-set/ 译者:浣熊君( ・᷄৺・᷅ )相关文章
- jmeter函数「uuid函数」
- 拍证件照前学会这七大技巧,让你好看百倍「证件照拍摄方法」
- 昆山数字化转型「苏州数智科技产业发展有限公司」
- 西安云摄影让同学聚会拍照更出彩吗「勇气让我更出彩」
- 产品如何利用视频推广引流「如何进行视频营销」
- 注重西安会议拍照服务细节避免影响会议照片质量的措施「会议拍照」
- 海关总署对3家境外水产品企业采取暂停进口措施「保税区海关监管办法」
- 昆山抖音运营团队「上海大众点评代运营」
- 195万人申领电子驾驶证「初次申领机动车驾驶证」
- 昆山经济发展模式「昆山模式」
- 西安古城墙怎么拍照「西安城墙拍照攻略」
- 大唐不夜城不让用三脚架「大唐不夜城路线」
- 今年的黑五「黑五持续多久」
- 出口跨境电商规模「虹桥自贸中心」
- 跨境电商黑五类产品「电商黑五是什么时候」
- 电商黑五类产品怎么玩「黑五海淘什么时候能到货」
- 淘宝美工需要学那些知识「淘宝美工需要系统的学什么」
- 7988元华为P50Pro「微澜浩海」新配色发布