用于优化Django的IntegrityError,并处理延迟数据库约束的工具。
项目描述
Django Integrity
Django Integrity包含用于控制延迟约束和处理Django项目中使用PostgreSQL的IntegrityError
的工具。
可延迟约束
一些PostgreSQL约束可以被定义为DEFERRABLE
。未延迟的约束将在每个命令之后立即进行检查。延迟约束的检查将推迟到事务结束。可延迟约束将默认为DEFERRED
或IMMEDIATE
。
django_integrity.constraints
中的实用程序可以确保延迟约束立即进行检查,或者延迟立即约束。
这些更改约束的状态直到当前事务结束
set_all_immediate(using=...)
set_immedate(names=(...), using=...)
set_deferred(names=(...), using=...)
要在事务的某些有限部分中立即强制约束,请使用immediate(names=(...), using=...)
上下文管理器。
为什么我们需要这个?
这通常在您想要捕获外键违规时很有用(例如:您插入了一行,该行引用了不存在的不同行)。
Django的外键约束默认是延迟的,所以它们通常只在事务结束时引发错误。使用try
捕获外键违规的IntegrityError
不起作用,您需要包装COMMIT
,这更复杂。
通过将约束设置为IMMEDIATE
,约束将在INSERT
时进行检查,这将更容易捕获。
更普遍地,如果您有一个自定义的可延迟约束,使用这些工具更改默认行为可能很有用。
细化IntegrityError
django_integrity.conversion
中的refine_integrity_error
上下文管理器会将IntegrityError
转换为基于规则映射到您自定义异常的更具体的异常,并在不匹配时引发IntegrityError
。
为什么我们需要这个?
当数据库约束被违反时,我们通常期望看到IntegrityError
。
有时我们需要更多关于错误的信息:是违反了唯一约束、检查约束还是非空约束?也许我们的ID列的32位整数已经用完了?在这些方面不够具体可能会导致我们捕获的异常不是我们期望的那个。
示例
from django_integrity import conversion
from users.models import User
class UserAlreadyExists(Exception): ...
class EmailCannotBeNull(Exception): ...
class EmailMustBeLowerCase(Exception): ...
def create_user(email: str) -> User:
"""
Creates a user with the provided email address.
Raises:
UserAlreadyExists: If the email was not unique.
EmailCannotBeNull: If the email was None.
EmailMustBeLowerCase: If the email had a non-lowercase character.
"""
rules = [
(conversion.Unique(model=User, fields=("email",)), UserAlreadyExists),
(conversion.NotNull(model=User, field="email"), EmailCannotBeNull),
(conversion.Named(name="constraint_islowercase"), EmailMustBeLowerCase),
]
with conversion.refine_integrity_error(rules):
User.objects.create(email=email)
支持的依赖项
此包已测试与以下版本兼容
- Python 3.10、3.11或3.12。
- Django 4.1、4.2或5.0。
- PostgreSQL 12至16。
- psycopg2和psycopg3。