Hi folks,

We've had check constraints for a while now and they're awesome.

I'd like to propose an alternative way to declare check constraints: at the
field level. This sounds like it's duplicating the feature but there are
some advantages that make this distinct from declaring at the model-level
from the meta:

   - Colocality: the check rules are close to the field they're concerned
   with
   - Reusability: Allows for bundling with custom field types
   - Good for checks concerned only with the field its declared on, for
   multiple fields recommended to continue to use Meta. (Kind of analogous to
   unique=True vs UniqueConstraint)

For example:

class Product(Model):
    price = DecimalField(..., check=Q(price__gte=0))
    ...
    other fields
    ...


    class Meta:
        constraints = [
            ... declare constraints here that are concerned with multiple
fields...
        ]


For more complex fields you can then bundle the check for reusability:

class PriceField(DecimalField):
    def contribute_to_class(self, ...):
        super().contribute_to_class(...)
        self.check = Q(**{f'{self.name}__gte': 0})


Some other points:

   - To be consistent with model-level check constraints they'd also need
   to participate in validate_constraints().
   - (Small)PositiveIntegerField already has its own implementation of a
   check constraint, enforcing values >- 0 via the private db_check() method.
   I think this is an example of how bundling checks can be useful.
   - I won't go into implementation alternatives but making use of this
   existing db_check() method is one possibility. How participation in
   validation would work would still need to be decided upon.
   - See this Stupid Django Trick
   
<https://github.com/shangxiao/stupid-django-tricks/tree/master/column_check_constraints>
   for some experimentation with this idea.


Cheers,
David

-- 
You received this message because you are subscribed to the Google Groups 
"Django developers  (Contributions to Django itself)" group.
To unsubscribe from this group and stop receiving emails from it, send an email 
to django-developers+unsubscr...@googlegroups.com.
To view this discussion on the web visit 
https://groups.google.com/d/msgid/django-developers/CADyZw-6Odv0dpo-En3Jm2NqPhBtK7ebaGKBi4OROe1n%2BvHEE-A%40mail.gmail.com.
  • Pro... David Sanders
    • ... 'Adam Johnson' via Django developers (Contributions to Django itself)
      • ... Mariusz Felisiak
        • ... 'Adam Johnson' via Django developers (Contributions to Django itself)
          • ... charettes
            • ... David Sanders

Reply via email to