Extends django check constraint to support annotations.
Project description
django-check-constraint
Extends Django's Check constraint with support for UDF(User defined functions/db functions) and annotations.
Installation
$ pip install django-check-constraint
ADD check_constraint
to list of INSTALLED APPS.
INSTALLED_APPS = [
...
"check_constraint",
...
]
Scenario:
Suppose you have a database function that returns the counts of null values in [i, ...n]
.
CREATE OR REPLACE FUNCTION public.non_null_count(VARIADIC arg_array ANYARRAY)
RETURNS BIGINT AS
$$
SELECT COUNT(x) FROM UNNEST($1) AS x
$$ LANGUAGE SQL IMMUTABLE;
Example:
SELECT public.non_null_count(1, null, null);
Outputs:
non_null_count
----------------
1
(1 row)
Defining a check constraint with this function
The equivalent of (PostgresSQL)
ALTER TABLE app_name_test_modoel ADD CONSTRAINT app_name_test_model_optional_field_provided
CHECK(non_null_count(amount::integer , amount_off::integer, percentage::integer) = 1);
Usage
Converting this to django functions and annotated check contraints can be done using:
function.py
from django.db.models import Func, SmallIntegerField, TextField
from django.db.models.functions import Cast
class NotNullCount(Func):
function = 'non_null_count'
def __init__(self, *expressions, **extra):
filter_exp = [
Cast(exp, TextField()) for exp in expressions if isinstance(exp, str)
]
if 'output_field' not in extra:
extra['output_field'] = SmallIntegerField()
if len(expressions) < 2:
raise ValueError('NotNullCount must take at least two expressions')
super().__init__(*filter_exp, **extra)
Creating annotated check constraints
from django.db import models
from django.db.models import Q
from check_constraint.models import AnnotatedCheckConstraint
class TestModel(models.Model):
amount = models.DecimalField(max_digits=9, decimal_places=2, null=True, blank=True)
amount_off = models.DecimalField(max_digits=7, decimal_places=2, null=True, blank=True)
percentage = models.DecimalField(max_digits=3, decimal_places=0, null=True, blank=True)
class Meta:
constraints = [
AnnotatedCheckConstraint(
check=Q(not_null_count=1),
annotations={
'not_null_count': (
NotNullCount(
'amount',
'amount_off',
'percentage',
)
),
},
name='%(app_label)s_%(class)s_optional_field_provided',
),
]
TODO's
- Add support for schema based functions.
- Add warning about mysql lack of user defined check constraint support.
- Remove skipped sqlite3 test.
Project details
Release history Release notifications | RSS feed
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
Close
Hashes for django-check-constraint-1.0.17.tar.gz
Algorithm | Hash digest | |
---|---|---|
SHA256 | dc6a77a4c0f69c2d7a5dba14bfe53ac328886548e60518e9145e4e4671a22d31 |
|
MD5 | 3857648d11acb08f8cbd7c7d613a6fc9 |
|
BLAKE2b-256 | ff5b88ac493279d6b9e50346271221b0e7c2ee849a70177db1d920f1969ef33b |
Close
Hashes for django_check_constraint-1.0.17-py3-none-any.whl
Algorithm | Hash digest | |
---|---|---|
SHA256 | 1c08fd853441846f91374a3ca6d03f04dd62356ecd61e1335d24cb293c257731 |
|
MD5 | d02d5047a88090eb316264cb8fb0cb1d |
|
BLAKE2b-256 | b302e50f8f6d7d4ae04f7d10315bf0cfcd9df8e301ec0cec990faeabd53ca72a |