Opened 10 years ago
Closed 10 years ago
#24837 closed New feature (fixed)
Unable to query DateField using DateRange
| Reported by: | Matthew Schinckel | Owned by: | |
|---|---|---|---|
| Component: | contrib.postgres | Version: | dev |
| Severity: | Normal | Keywords: | |
| Cc: | Triage Stage: | Ready for checkin | |
| Has patch: | no | Needs documentation: | no |
| Needs tests: | no | Patch needs improvement: | no |
| Easy pickings: | no | UI/UX: | no |
Description
MyModel.objects.filter(datefield__contained_by=DateRange(...))
The lookup is not defined on that field:
FieldError: Unsupported lookup 'contained_by' for IntegerField or join on the field not permitted.
Change History (8)
comment:1 by , 10 years ago
comment:2 by , 10 years ago
In the past, I have written a Range field, and a lookup to use Range types, however I was not using Lookup.process_rhs(qn, connection): instead I was first looking to see if the rhs argument was a range type, and if it was, then just letting that go through.
Part of that test was inspecting a string argument and seeing if it matched a regex, which is probably not as hygienic as actually processing the argument correctly.
comment:3 by , 10 years ago
| Easy pickings: | unset |
|---|---|
| Triage Stage: | Unreviewed → Accepted |
| Type: | Uncategorized → New feature |
| Version: | 1.8 → master |
comment:4 by , 10 years ago
I've made some progress, see https://github.com/django/django/compare/master...mjtamlyn:query-with-ranges
There is no operator for not_contained_by in postgres so I removed that pseudocode from schinckel's branch.
The code passes the tests but needs some serious tidying up to cover non-simple use cases (F objects, complex expressions with output types etc). Sadly a lot of explicit typecasting is required to make postgres not freak out. As a result, I think we likely should just support "matching" operations. For example this means big integer in a big integer range, datetime in a datetime range not a date range.
comment:5 by , 10 years ago
Hmm. Is casting a datetime to a date (i.e., in python doing a .date()) going to give the same result as doing the comparison in the database with a datetime (contained by a daterange)?
My gut feeling is yes, but I may not have had enough coffee this morning to make an educated guess.
comment:6 by , 10 years ago
I know it _should_ just work, but is it worth having tests for .exclude(...__contained_by=...) worthwhile?
comment:7 by , 10 years ago
| Triage Stage: | Accepted → Ready for checkin |
|---|
I have a partial implementation, showing the next possible issue.
That is, the date field is attempting to coerce the lookup value into a date:
====================================================================== ERROR: test_datetime_range (postgres_tests.test_ranges.TestQueringWithRanges) ---------------------------------------------------------------------- Traceback (most recent call last): File "/Users/matt/Development/django/tests/postgres_tests/test_ranges.py", line 238, in test_datetime_range RangeLookupsModel.objects.filter(timestamp__contained_by=DateTimeTZRange('2015-01-01T09:00', '2015-05-04T23:55')), File "/Users/matt/Development/django/django/db/models/manager.py", line 125, in manager_method return getattr(self.get_queryset(), name)(*args, **kwargs) File "/Users/matt/Development/django/django/db/models/query.py", line 781, in filter return self._filter_or_exclude(False, *args, **kwargs) File "/Users/matt/Development/django/django/db/models/query.py", line 799, in _filter_or_exclude clone.query.add_q(Q(*args, **kwargs)) File "/Users/matt/Development/django/django/db/models/sql/query.py", line 1236, in add_q clause, _ = self._add_q(q_object, self.used_aliases) File "/Users/matt/Development/django/django/db/models/sql/query.py", line 1262, in _add_q allow_joins=allow_joins, split_subq=split_subq, File "/Users/matt/Development/django/django/db/models/sql/query.py", line 1196, in build_filter condition = self.build_lookup(lookups, col, value) File "/Users/matt/Development/django/django/db/models/sql/query.py", line 1095, in build_lookup return final_lookup(lhs, rhs) File "/Users/matt/Development/django/django/db/models/lookups.py", line 98, in __init__ self.rhs = self.get_prep_lookup() File "/Users/matt/Development/django/django/db/models/lookups.py", line 136, in get_prep_lookup return self.lhs.output_field.get_prep_lookup(self.lookup_name, self.rhs) File "/Users/matt/Development/django/django/db/models/fields/__init__.py", line 734, in get_prep_lookup return self.get_prep_value(value) File "/Users/matt/Development/django/django/db/models/fields/__init__.py", line 1432, in get_prep_value value = super(DateTimeField, self).get_prep_value(value) File "/Users/matt/Development/django/django/db/models/fields/__init__.py", line 1288, in get_prep_value return self.to_python(value) File "/Users/matt/Development/django/django/db/models/fields/__init__.py", line 1391, in to_python parsed = parse_datetime(value) File "/Users/matt/Development/django/django/utils/dateparse.py", line 93, in parse_datetime match = datetime_re.match(value) TypeError: expected string or bufferhttps://github.com/schinckel/django/tree/query-with-ranges