Opened 3 years ago

Last modified 3 years ago

#33344 closed New feature

Define bounds transform for discrete postgres range fields — at Initial Version

Reported by: Vidir Valberg Gudmundsson Owned by:
Component: contrib.postgres Version: dev
Severity: Normal Keywords:
Cc: Triage Stage: Unreviewed
Has patch: no Needs documentation: no
Needs tests: no Patch needs improvement: no
Easy pickings: no UI/UX: no

Description

The fix for https://code.djangoproject.com/ticket/27147 adressed the issue of non-discrete range types. Left is the issue of how the ranges are "represented" when brought back from the database.

At $WORK we have a model like so:

class Foo(models.Model):
    ...
    period = models.DateRangeField()

The problem arises when we display the periods of multiple Foos. Using the default bound of [) returned by postgres means that adjacent Foos "visually" share a date in the upper of one and lower of the other. We could of course handle this each time we output the value by decrementing the upper value. But this is a bit error prone and can lead to confusions.

I propose that we add the following to django.contrib.postres.fields.ranges (heavily inspired by Jakub Skałeckis comment at https://code.djangoproject.com/ticket/27147#comment:8):

class DiscreteRangeField(RangeField):

    def __init__(self, *args, bounds_transform=CANONICAL_RANGE_BOUNDS, **kwargs):
        if bounds_transform not in ALLOWED_BOUNDS:
            raise ValueError("bounds_transform must be one of '[)', '(]', '()', or '[]'.")
        self.bounds_transform = bounds_transform
        super().__init__(*args, **kwargs)

    def from_db_value(self, value, expression, connection):
        if value is None:
            return

        if self.bounds_transform[0] == "(" and value.lower:
            value._lower = value.lower - self.bounds_transform_unit

        if self.bounds_transform[1] == "]" and value.upper:
            value._lower = value.upper - self.bounds_transform_unit

        value._bounds = self.bounds_transform
        return value

and make IntegerRangeField, BigIntegerRangeField and DateRangeField inherit from DiscreteRangeField.

I have already written some tests, and if there are no big gotchas to this approach I would love to submit a PR in the next couple of days.

Change History (0)

Note: See TracTickets for help on using tickets.
Back to Top