mirror of
https://github.com/django/django.git
synced 2025-08-04 19:08:28 +00:00
Fixed #24837 -- field__contained_by=Range
Provide `contained_by` lookups for the equivalent single valued fields related to the range field types. This acts as the opposite direction to rangefield__contains. With thanks to schinckel for the idea and initial tests.
This commit is contained in:
parent
5987b3c46d
commit
7bda2d8ebc
6 changed files with 175 additions and 3 deletions
|
@ -143,6 +143,21 @@ class Migration(migrations.Migration):
|
|||
('timestamps', DateTimeRangeField(null=True, blank=True)),
|
||||
('dates', DateRangeField(null=True, blank=True)),
|
||||
],
|
||||
options={
|
||||
'required_db_vendor': 'postgresql'
|
||||
},
|
||||
bases=(models.Model,)
|
||||
),
|
||||
migrations.CreateModel(
|
||||
name='RangeLookupsModel',
|
||||
fields=[
|
||||
('parent', models.ForeignKey('postgres_tests.RangesModel', blank=True, null=True)),
|
||||
('integer', models.IntegerField(blank=True, null=True)),
|
||||
('big_integer', models.BigIntegerField(blank=True, null=True)),
|
||||
('float', models.FloatField(blank=True, null=True)),
|
||||
('timestamp', models.DateTimeField(blank=True, null=True)),
|
||||
('date', models.DateField(blank=True, null=True)),
|
||||
],
|
||||
options={
|
||||
'required_db_vendor': 'postgresql',
|
||||
},
|
||||
|
|
|
@ -60,11 +60,23 @@ if connection.vendor == 'postgresql' and connection.pg_version >= 90200:
|
|||
floats = FloatRangeField(blank=True, null=True)
|
||||
timestamps = DateTimeRangeField(blank=True, null=True)
|
||||
dates = DateRangeField(blank=True, null=True)
|
||||
|
||||
class RangeLookupsModel(PostgreSQLModel):
|
||||
parent = models.ForeignKey(RangesModel, blank=True, null=True)
|
||||
integer = models.IntegerField(blank=True, null=True)
|
||||
big_integer = models.BigIntegerField(blank=True, null=True)
|
||||
float = models.FloatField(blank=True, null=True)
|
||||
timestamp = models.DateTimeField(blank=True, null=True)
|
||||
date = models.DateField(blank=True, null=True)
|
||||
|
||||
else:
|
||||
# create an object with this name so we don't have failing imports
|
||||
class RangesModel(object):
|
||||
pass
|
||||
|
||||
class RangeLookupsModel(object):
|
||||
pass
|
||||
|
||||
|
||||
# Only create this model for postgres >= 9.4
|
||||
if connection.vendor == 'postgresql' and connection.pg_version >= 90400:
|
||||
|
|
|
@ -5,11 +5,12 @@ import unittest
|
|||
from django import forms
|
||||
from django.core import exceptions, serializers
|
||||
from django.db import connection
|
||||
from django.db.models import F
|
||||
from django.test import TestCase, override_settings
|
||||
from django.utils import timezone
|
||||
|
||||
from . import PostgreSQLTestCase
|
||||
from .models import RangesModel
|
||||
from .models import RangeLookupsModel, RangesModel
|
||||
|
||||
try:
|
||||
from psycopg2.extras import DateRange, DateTimeTZRange, NumericRange
|
||||
|
@ -197,6 +198,96 @@ class TestQuerying(TestCase):
|
|||
)
|
||||
|
||||
|
||||
@skipUnlessPG92
|
||||
class TestQueringWithRanges(TestCase):
|
||||
def test_date_range(self):
|
||||
objs = [
|
||||
RangeLookupsModel.objects.create(date='2015-01-01'),
|
||||
RangeLookupsModel.objects.create(date='2015-05-05'),
|
||||
]
|
||||
self.assertSequenceEqual(
|
||||
RangeLookupsModel.objects.filter(date__contained_by=DateRange('2015-01-01', '2015-05-04')),
|
||||
[objs[0]],
|
||||
)
|
||||
|
||||
def test_date_range_datetime_field(self):
|
||||
objs = [
|
||||
RangeLookupsModel.objects.create(timestamp='2015-01-01'),
|
||||
RangeLookupsModel.objects.create(timestamp='2015-05-05'),
|
||||
]
|
||||
self.assertSequenceEqual(
|
||||
RangeLookupsModel.objects.filter(timestamp__date__contained_by=DateRange('2015-01-01', '2015-05-04')),
|
||||
[objs[0]],
|
||||
)
|
||||
|
||||
def test_datetime_range(self):
|
||||
objs = [
|
||||
RangeLookupsModel.objects.create(timestamp='2015-01-01T09:00:00'),
|
||||
RangeLookupsModel.objects.create(timestamp='2015-05-05T17:00:00'),
|
||||
]
|
||||
self.assertSequenceEqual(
|
||||
RangeLookupsModel.objects.filter(
|
||||
timestamp__contained_by=DateTimeTZRange('2015-01-01T09:00', '2015-05-04T23:55')
|
||||
),
|
||||
[objs[0]],
|
||||
)
|
||||
|
||||
def test_integer_range(self):
|
||||
objs = [
|
||||
RangeLookupsModel.objects.create(integer=5),
|
||||
RangeLookupsModel.objects.create(integer=99),
|
||||
RangeLookupsModel.objects.create(integer=-1),
|
||||
]
|
||||
self.assertSequenceEqual(
|
||||
RangeLookupsModel.objects.filter(integer__contained_by=NumericRange(1, 98)),
|
||||
[objs[0]]
|
||||
)
|
||||
|
||||
def test_biginteger_range(self):
|
||||
objs = [
|
||||
RangeLookupsModel.objects.create(big_integer=5),
|
||||
RangeLookupsModel.objects.create(big_integer=99),
|
||||
RangeLookupsModel.objects.create(big_integer=-1),
|
||||
]
|
||||
self.assertSequenceEqual(
|
||||
RangeLookupsModel.objects.filter(big_integer__contained_by=NumericRange(1, 98)),
|
||||
[objs[0]]
|
||||
)
|
||||
|
||||
def test_float_range(self):
|
||||
objs = [
|
||||
RangeLookupsModel.objects.create(float=5),
|
||||
RangeLookupsModel.objects.create(float=99),
|
||||
RangeLookupsModel.objects.create(float=-1),
|
||||
]
|
||||
self.assertSequenceEqual(
|
||||
RangeLookupsModel.objects.filter(float__contained_by=NumericRange(1, 98)),
|
||||
[objs[0]]
|
||||
)
|
||||
|
||||
def test_f_ranges(self):
|
||||
parent = RangesModel.objects.create(floats=NumericRange(0, 10))
|
||||
objs = [
|
||||
RangeLookupsModel.objects.create(float=5, parent=parent),
|
||||
RangeLookupsModel.objects.create(float=99, parent=parent),
|
||||
]
|
||||
self.assertSequenceEqual(
|
||||
RangeLookupsModel.objects.filter(float__contained_by=F('parent__floats')),
|
||||
[objs[0]]
|
||||
)
|
||||
|
||||
def test_exclude(self):
|
||||
objs = [
|
||||
RangeLookupsModel.objects.create(float=5),
|
||||
RangeLookupsModel.objects.create(float=99),
|
||||
RangeLookupsModel.objects.create(float=-1),
|
||||
]
|
||||
self.assertSequenceEqual(
|
||||
RangeLookupsModel.objects.exclude(float__contained_by=NumericRange(0, 100)),
|
||||
[objs[2]]
|
||||
)
|
||||
|
||||
|
||||
@skipUnlessPG92
|
||||
class TestSerialization(TestCase):
|
||||
test_data = (
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue