Michael Samoylov
Michael Samoylov

Reputation: 3093

Django PostgreSQL IntegerRangeField and update_or_create

I have a pretty simple model:

from django.contrib.postgres.fields import IntegerRangeField
from django.db import models


class Production(models.Model):
    title = models.CharField(max_length=100, blank=True, db_index=True)
    year = models.PositiveSmallIntegerField(blank=True, default=0, db_index=True)
    index = models.PositiveSmallIntegerField(blank=True, default=0)
    run_years = IntegerRangeField(blank=True, null=True)

    class Meta:
        unique_together = ('title', 'year', 'index')

But, I'm experiencing a very strange behavior when I'm manipulating my model through update_or_create method. For some reason my IntegerRange field gets just wiped.

In [1]: Production.objects.update_or_create(**{'title': '#twentyfiveish', 'year': 2017, 
        'index': 0, 'run_years': (2017, 2017)})[0].run_years
Out[1]: (2017, 2017)

In [2]: Production.objects.update_or_create(**{'title': '#twentyfiveish', 'year': 2017, 
        'index': 0, 'run_years': (2017, 2017)})[0].run_years
Out[2]: NumericRange(empty=True)

That doesn't look as a desired behavior to me. Is it a bug or not? Please advise.

Versions:

Upvotes: 1

Views: 562

Answers (1)

rm -rf
rm -rf

Reputation: 191

Unfortunately, this is "as designed". Putting together

Regardless of the bounds specified when saving the data, PostgreSQL always returns a range in a canonical form that includes the lower bound and excludes the upper bound; that is [).

and

-- includes no points (and will be normalized to 'empty')
SELECT '[4,4)'::int4range;

(from https://www.postgresql.org/docs/9.3/static/rangetypes.html)

You are out of luck. There is, however, a feature request for this, https://code.djangoproject.com/ticket/27147.

Fwiw, psycopg2 supports all range bounds types.

Options?

  1. One off custom sql (yuck)
  2. Implement the Django feature request and submit a PR
  3. Just use 2 int columns (fastest)

Upvotes: 2

Related Questions