I agree this feature would be useful, at least to allow bundling check
constraints with custom field classes. As you point out the
PositiveIntegerField classes do this within Django, and doubtless many
custom fields have used the db_check() method.

The only thing I'm not a fan of in your proposal is repeating the field
name within the check expression, like "price" in:

price = DecimalField(..., check=Q(price__gte=0))

This seems repetitive at least, and would increase error refactoring. Also
Django field classes typically don't “know” their name until the Model meta
class logic runs, and contribute_to_class() is called. Requiring the name
within check() would mean it would need to accept any name and validate it
later.

Perhaps we could support only a special name instead, like “self” or the
shorter “f”?

price = DecimalField(..., check=Q(f__gte=0))

On Wed, Apr 5, 2023 at 7:18 PM David Sanders <shang.xiao.sand...@gmail.com>
wrote:

> 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
> <https://groups.google.com/d/msgid/django-developers/CADyZw-6Odv0dpo-En3Jm2NqPhBtK7ebaGKBi4OROe1n%2BvHEE-A%40mail.gmail.com?utm_medium=email&utm_source=footer>
> .
>

-- 
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/CAMyDDM3Tyj%3Djfo9yFiUythymjP2WHKGi6cJY%3DOKk1_XkggiMtQ%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