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
File details
Details for the file django-check-constraint-1.0.18.tar.gz
.
File metadata
- Download URL: django-check-constraint-1.0.18.tar.gz
- Upload date:
- Size: 13.6 kB
- Tags: Source
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/3.1.1 pkginfo/1.5.0.1 requests/2.23.0 setuptools/45.2.0 requests-toolbelt/0.9.1 tqdm/4.43.0 CPython/3.6.10
File hashes
Algorithm | Hash digest | |
---|---|---|
SHA256 | e1fc7074def6a21576a3170f59e0c656163f81c0fb2962723980016877e35f07 |
|
MD5 | 466c000560b90ffeb52b508f1ace4e79 |
|
BLAKE2b-256 | d330d113b6f1a2f0a0422f5853ec49885bdd1bd59a9634b751d834a505609cf5 |
File details
Details for the file django_check_constraint-1.0.18-py3-none-any.whl
.
File metadata
- Download URL: django_check_constraint-1.0.18-py3-none-any.whl
- Upload date:
- Size: 14.5 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/3.1.1 pkginfo/1.5.0.1 requests/2.23.0 setuptools/45.2.0 requests-toolbelt/0.9.1 tqdm/4.43.0 CPython/3.6.10
File hashes
Algorithm | Hash digest | |
---|---|---|
SHA256 | 2dd1942d1314415ab93b7a2242a34139b576069b58d9aaeb70b810cc13f6578f |
|
MD5 | e23b635194d38c0705b25f9d5f0829d6 |
|
BLAKE2b-256 | 1c741d10331fbce9104a9d669c816a304863e3cc114a4d3824279a712459a61d |