[Django] #30758: Postgres DateTimeRangeField crash in django admin (AttributeError: 'builtin_function_or_method' object has no attribute 'strip')

25 views
Skip to first unread message

Django

unread,
Sep 4, 2019, 8:43:59 AM9/4/19
to django-...@googlegroups.com
#30758: Postgres DateTimeRangeField crash in django admin (AttributeError:
'builtin_function_or_method' object has no attribute 'strip')
-------------------------------------+-------------------------------------
Reporter: yeppus | Owner: (none)
Type: Bug | Status: new
Component: | Version: 2.2
contrib.postgres |
Severity: Normal | Keywords: DateTimeRangeField
Triage Stage: | Has patch: 0
Unreviewed |
Needs documentation: 0 | Needs tests: 0
Patch needs improvement: 0 | Easy pickings: 0
UI/UX: 0 |
-------------------------------------+-------------------------------------
When trying to save an object that has a DateTimeRangeField in django
admin the following error occurs:
AttributeError: 'builtin_function_or_method' object has no attribute
'strip'

When trying to determine if the value has changed it, maybe accidentally,
assigns initial value the function "lower" instead of the value.

Later it tries to run .strip() on the function.

This all worked in django 1.11 and I can not find any mentioned of changed
behaviour for Django 2.2.


**django/contrib/postgres/forms/ranges.py: 101**
{{{
#!div style="font-size: 80%"
Code highlighting:
{{{#!python
class RangeWidget(MultiWidget):
def __init__(self, base_widget, attrs=None):
widgets = (base_widget, base_widget)
super().__init__(widgets, attrs)

def decompress(self, value):
if value:
return (value.lower, value.upper) ### <<-- RETURNS CALLABLE,
NOT VALUE
return (None, None)
}}}
}}}

**django/forms/fields.py: 1060**
{{{
#!div style="font-size: 80%"
Code highlighting:
{{{#!python
def has_changed(self, initial, data):
if self.disabled:
return False
if initial is None:
initial = ['' for x in range(0, len(data))]
else:
if not isinstance(initial, list):
initial = self.widget.decompress(initial) ### <<--
RECEIVES CALLABLE, NOT VALUE
for field, initial, data in zip(self.fields, initial, data):
try:
initial = field.to_python(initial) ### <<-- TRIES
to_python with CALLABLE
except ValidationError:
return True
if field.has_changed(initial, data):
return True
return False
}}}
}}}

**django/forms/fields.py: 450**
{{{
#!div style="font-size: 80%"
Code highlighting:
{{{#!python
def to_python(self, value):
"""
Validate that the input can be converted to a datetime. Return a
Python datetime.datetime object.
"""
if value in self.empty_values:
return None
if isinstance(value, datetime.datetime):
return from_current_timezone(value)
if isinstance(value, datetime.date):
result = datetime.datetime(value.year, value.month, value.day)
return from_current_timezone(result)
result = super().to_python(value) ### <<-- ENDS UP HERE SENDING
CALLABLE TO PARENT
return from_current_timezone(result)
}}}
}}}

BaseTemporalField.to_python expects a string and runs .strip() which
generates AttributeError and crashes.


Traceback (most recent call last):
File "/Users/joakim/.pyenv/versions/3.5.2/lib/python3.5/site-
packages/django/core/handlers/exception.py", line 34, in inner
response = get_response(request)
File "/Users/joakim/.pyenv/versions/3.5.2/lib/python3.5/site-
packages/django/core/handlers/base.py", line 115, in _get_response
response = self.process_exception_by_middleware(e, request)
File "/Users/joakim/.pyenv/versions/3.5.2/lib/python3.5/site-
packages/django/core/handlers/base.py", line 113, in _get_response
response = wrapped_callback(request, *callback_args,
**callback_kwargs)
File "/Users/joakim/.pyenv/versions/3.5.2/lib/python3.5/site-
packages/django/contrib/admin/options.py", line 606, in wrapper
return self.admin_site.admin_view(view)(*args, **kwargs)
File "/Users/joakim/.pyenv/versions/3.5.2/lib/python3.5/site-
packages/django/utils/decorators.py", line 142, in _wrapped_view
response = view_func(request, *args, **kwargs)
File "/Users/joakim/.pyenv/versions/3.5.2/lib/python3.5/site-
packages/django/views/decorators/cache.py", line 44, in _wrapped_view_func
response = view_func(request, *args, **kwargs)
File "/Users/joakim/.pyenv/versions/3.5.2/lib/python3.5/site-
packages/django/contrib/admin/sites.py", line 223, in inner
return view(request, *args, **kwargs)
File "/Users/joakim/.pyenv/versions/3.5.2/lib/python3.5/site-
packages/django/contrib/admin/options.py", line 1637, in change_view
return self.changeform_view(request, object_id, form_url,
extra_context)
File "/Users/joakim/.pyenv/versions/3.5.2/lib/python3.5/site-
packages/django/utils/decorators.py", line 45, in _wrapper
return bound_method(*args, **kwargs)
File "/Users/joakim/.pyenv/versions/3.5.2/lib/python3.5/site-
packages/django/utils/decorators.py", line 142, in _wrapped_view
response = view_func(request, *args, **kwargs)
File "/Users/joakim/.pyenv/versions/3.5.2/lib/python3.5/site-
packages/django/contrib/admin/options.py", line 1522, in changeform_view
return self._changeform_view(request, object_id, form_url,
extra_context)
File "/Users/joakim/.pyenv/versions/3.5.2/lib/python3.5/site-
packages/django/contrib/admin/options.py", line 1560, in _changeform_view
if all_valid(formsets) and form_validated:
File "/Users/joakim/.pyenv/versions/3.5.2/lib/python3.5/site-
packages/django/forms/formsets.py", line 448, in all_valid
valid &= formset.is_valid()
File "/Users/joakim/.pyenv/versions/3.5.2/lib/python3.5/site-
packages/django/forms/formsets.py", line 301, in is_valid
self.errors
File "/Users/joakim/.pyenv/versions/3.5.2/lib/python3.5/site-
packages/django/forms/formsets.py", line 281, in errors
self.full_clean()
File "/Users/joakim/.pyenv/versions/3.5.2/lib/python3.5/site-
packages/django/forms/formsets.py", line 325, in full_clean
if not form.has_changed() and i >= self.initial_form_count():
File "/Users/joakim/.pyenv/versions/3.5.2/lib/python3.5/site-
packages/django/contrib/admin/options.py", line 2111, in has_changed
return super().has_changed()
File "/Users/joakim/.pyenv/versions/3.5.2/lib/python3.5/site-
packages/django/forms/forms.py", line 434, in has_changed
return bool(self.changed_data)
File "/Users/joakim/.pyenv/versions/3.5.2/lib/python3.5/site-
packages/django/utils/functional.py", line 80, in __get__
res = instance.__dict__[self.name] = self.func(instance)
File "/Users/joakim/.pyenv/versions/3.5.2/lib/python3.5/site-
packages/django/forms/forms.py", line 456, in changed_data
if field.has_changed(initial_value, data_value):
File "/Users/joakim/.pyenv/versions/3.5.2/lib/python3.5/site-
packages/django/forms/fields.py", line 1070, in has_changed
initial = field.to_python(initial)
File "/Users/joakim/.pyenv/versions/3.5.2/lib/python3.5/site-
packages/django/forms/fields.py", line 462, in to_python
result = super().to_python(value)
File "/Users/joakim/.pyenv/versions/3.5.2/lib/python3.5/site-
packages/django/forms/fields.py", line 379, in to_python
value = value.strip()

--
Ticket URL: <https://code.djangoproject.com/ticket/30758>
Django <https://code.djangoproject.com/>
The Web framework for perfectionists with deadlines.

Django

unread,
Sep 4, 2019, 8:51:54 AM9/4/19
to django-...@googlegroups.com
#30758: Postgres DateTimeRangeField crash in django admin (AttributeError:
'builtin_function_or_method' object has no attribute 'strip')
------------------------------------+--------------------------------------

Reporter: yeppus | Owner: (none)
Type: Bug | Status: new
Component: contrib.postgres | Version: 2.2
Severity: Normal | Resolution:
Keywords: DateTimeRangeField | Triage Stage: Unreviewed
Has patch: 0 | Needs documentation: 0

Needs tests: 0 | Patch needs improvement: 0
Easy pickings: 0 | UI/UX: 0
------------------------------------+--------------------------------------
Description changed by felixxm:

Old description:

New description:

--

--
Ticket URL: <https://code.djangoproject.com/ticket/30758#comment:1>

Django

unread,
Sep 5, 2019, 6:57:40 AM9/5/19
to django-...@googlegroups.com
#30758: DateTimeRangeField crashes in django admin (object has no attribute
'strip').
------------------------------------+--------------------------------------
Reporter: yeppus | Owner: (none)
Type: Bug | Status: closed
Component: contrib.postgres | Version: master
Severity: Normal | Resolution: needsinfo

Keywords: DateTimeRangeField | Triage Stage: Unreviewed
Has patch: 0 | Needs documentation: 0

Needs tests: 0 | Patch needs improvement: 0
Easy pickings: 0 | UI/UX: 0
------------------------------------+--------------------------------------
Changes (by felixxm):

* status: new => closed
* version: 2.2 => master
* resolution: => needsinfo


Comment:

`value.lower` and `value.upper` are not callable they are lower and upper
bound of a range. I'm not able to reproduce this issue in Django 2.2 or on
a current master. It works for me with inlines and a direct form. Please
provide a sample (minimal) project to reproduce this issue.

--
Ticket URL: <https://code.djangoproject.com/ticket/30758#comment:2>

Django

unread,
Sep 6, 2019, 4:59:50 AM9/6/19
to django-...@googlegroups.com
#30758: DateTimeRangeField crashes in django admin (object has no attribute
'strip').
------------------------------------+--------------------------------------
Reporter: yeppus | Owner: (none)
Type: Bug | Status: new
Component: contrib.postgres | Version: master
Severity: Normal | Resolution:
Keywords: DateTimeRangeField | Triage Stage: Unreviewed
Has patch: 0 | Needs documentation: 0

Needs tests: 0 | Patch needs improvement: 0
Easy pickings: 0 | UI/UX: 0
------------------------------------+--------------------------------------
Changes (by yeppus):

* status: closed => new
* resolution: needsinfo =>


Comment:

It seems to be connected to default function. After some digging and
testing I managed to make a minimal testcase.

**admin.py**


{{{
#!div style="font-size: 80%"
Code highlighting:
{{{#!python

from django.contrib import admin
from . import models


@admin.register(models.DateRangeWithDefaultFunction)
class PriceAdmin(admin.ModelAdmin):
fields = (
'valid_period',
)
list_display = (
'__str__',
)


@admin.register(models.DateRangeWithoutDefaultFunction)
class PriceAdmin(admin.ModelAdmin):
fields = (
'valid_period',
)
list_display = (
'__str__',
)
}}}
}}}

**models.py**


{{{
#!div style="font-size: 80%"
Code highlighting:
{{{#!python

from django.db import models
from django.utils import timezone
from django.contrib.postgres import fields as pg_fields
from psycopg2._range import DateTimeTZRange


def default_period():
return DateTimeTZRange(
lower=timezone.now(),
upper=None,
)

#Can add new but not change objects in admin
class DateRangeWithDefaultFunction(models.Model):

valid_period = pg_fields.DateTimeRangeField(
'valid during',
blank=True,
default=default_period,
)

#Working as expected
class DateRangeWithoutDefaultFunction(models.Model):
valid_period = pg_fields.DateTimeRangeField(
'valid during',
blank=True,
)
}}}
}}}

--
Ticket URL: <https://code.djangoproject.com/ticket/30758#comment:3>

Django

unread,
Sep 6, 2019, 5:48:41 AM9/6/19
to django-...@googlegroups.com
#30758: DateTimeRangeField with default crashes in django admin (object has no
attribute 'strip').
------------------------------------+------------------------------------

Reporter: yeppus | Owner: (none)
Type: Bug | Status: new
Component: contrib.postgres | Version: master
Severity: Normal | Resolution:
Keywords: DateTimeRangeField | Triage Stage: Accepted
Has patch: 0 | Needs documentation: 0

Needs tests: 0 | Patch needs improvement: 0
Easy pickings: 0 | UI/UX: 0
------------------------------------+------------------------------------
Changes (by felixxm):

* stage: Unreviewed => Accepted


Comment:

Thanks for info! I can confirm that this issue is caused by `default`.

--
Ticket URL: <https://code.djangoproject.com/ticket/30758#comment:4>

Django

unread,
Sep 8, 2019, 12:37:44 PM9/8/19
to django-...@googlegroups.com
#30758: DateTimeRangeField with default crashes in django admin (object has no
attribute 'strip').
-------------------------------------+-------------------------------------
Reporter: yeppus | Owner: Nasir
| Hussain
Type: Bug | Status: assigned

Component: contrib.postgres | Version: master
Severity: Normal | Resolution:
Keywords: DateTimeRangeField | Triage Stage: Accepted
Has patch: 0 | Needs documentation: 0

Needs tests: 0 | Patch needs improvement: 0
Easy pickings: 0 | UI/UX: 0
-------------------------------------+-------------------------------------
Changes (by Nasir Hussain):

* owner: (none) => Nasir Hussain
* status: new => assigned


--
Ticket URL: <https://code.djangoproject.com/ticket/30758#comment:5>

Django

unread,
Sep 8, 2019, 12:55:10 PM9/8/19
to django-...@googlegroups.com
#30758: DateTimeRangeField with default crashes in django admin (object has no
attribute 'strip').
-------------------------------------+-------------------------------------
Reporter: yeppus | Owner: Nasir
| Hussain
Type: Bug | Status: assigned
Component: contrib.postgres | Version: master
Severity: Normal | Resolution:
Keywords: DateTimeRangeField | Triage Stage: Accepted
Has patch: 1 | Needs documentation: 0

Needs tests: 0 | Patch needs improvement: 0
Easy pickings: 0 | UI/UX: 0
-------------------------------------+-------------------------------------
Changes (by Nasir Hussain):

* has_patch: 0 => 1


Comment:

I've created a [https://github.com/django/django/pull/11755 PR].

--
Ticket URL: <https://code.djangoproject.com/ticket/30758#comment:6>

Django

unread,
Sep 8, 2019, 2:25:29 PM9/8/19
to django-...@googlegroups.com
#30758: DateTimeRangeField with default crashes in django admin (object has no
attribute 'strip').
-------------------------------------+-------------------------------------
Reporter: yeppus | Owner: Nasir
| Hussain
Type: Bug | Status: assigned
Component: contrib.postgres | Version: master
Severity: Normal | Resolution:
Keywords: DateTimeRangeField | Triage Stage: Accepted
Has patch: 1 | Needs documentation: 0
Needs tests: 1 | Patch needs improvement: 0

Easy pickings: 0 | UI/UX: 0
-------------------------------------+-------------------------------------
Changes (by Claude Paroz):

* needs_tests: 0 => 1


Comment:

Thanks for the PR, now a test is still required.

--
Ticket URL: <https://code.djangoproject.com/ticket/30758#comment:7>

Django

unread,
Sep 8, 2019, 4:49:59 PM9/8/19
to django-...@googlegroups.com
#30758: DateTimeRangeField with default crashes in django admin (object has no
attribute 'strip').
-------------------------------------+-------------------------------------
Reporter: yeppus | Owner: Nasir
| Hussain
Type: Bug | Status: assigned
Component: contrib.postgres | Version: master
Severity: Normal | Resolution:
Keywords: DateTimeRangeField | Triage Stage: Accepted
Has patch: 1 | Needs documentation: 0

Needs tests: 0 | Patch needs improvement: 0
Easy pickings: 0 | UI/UX: 0
-------------------------------------+-------------------------------------
Changes (by Nasir Hussain):

* needs_tests: 1 => 0


Comment:

Replying to [comment:7 Claude Paroz]:


> Thanks for the PR, now a test is still required.

Added a test case which fails in case of master and passes with the fix.

--
Ticket URL: <https://code.djangoproject.com/ticket/30758#comment:8>

Django

unread,
Sep 10, 2019, 6:10:01 AM9/10/19
to django-...@googlegroups.com
#30758: DateTimeRangeField with default crashes in django admin (object has no
attribute 'strip').
-------------------------------------+-------------------------------------
Reporter: yeppus | Owner: Nasir
| Hussain
Type: Bug | Status: assigned
Component: contrib.postgres | Version: master
Severity: Normal | Resolution:
Keywords: DateTimeRangeField | Triage Stage: Accepted
Has patch: 1 | Needs documentation: 0

Needs tests: 0 | Patch needs improvement: 0
Easy pickings: 0 | UI/UX: 0
-------------------------------------+-------------------------------------

Comment (by yeppus):

Hi All, I can confirm that this patch works on our product staging
environment where we previously encounter the issue as well.

--
Ticket URL: <https://code.djangoproject.com/ticket/30758#comment:9>

Django

unread,
Sep 13, 2019, 6:22:10 AM9/13/19
to django-...@googlegroups.com
#30758: DateTimeRangeField with default crashes in django admin (object has no
attribute 'strip').
-------------------------------------+-------------------------------------
Reporter: yeppus | Owner: Nasir
| Hussain
Type: Bug | Status: assigned
Component: contrib.postgres | Version: master
Severity: Normal | Resolution:
Keywords: DateTimeRangeField | Triage Stage: Accepted
Has patch: 1 | Needs documentation: 0
Needs tests: 1 | Patch needs improvement: 1

Easy pickings: 0 | UI/UX: 0
-------------------------------------+-------------------------------------
Changes (by felixxm):

* needs_better_patch: 0 => 1


* needs_tests: 0 => 1


--
Ticket URL: <https://code.djangoproject.com/ticket/30758#comment:10>

Django

unread,
Sep 14, 2019, 4:10:02 PM9/14/19
to django-...@googlegroups.com
#30758: DateTimeRangeField with default crashes in django admin (object has no
attribute 'strip').
-------------------------------------+-------------------------------------
Reporter: yeppus | Owner: Nasir
| Hussain
Type: Bug | Status: assigned
Component: contrib.postgres | Version: master
Severity: Normal | Resolution:
Keywords: DateTimeRangeField | Triage Stage: Accepted
Has patch: 1 | Needs documentation: 0

Needs tests: 0 | Patch needs improvement: 0
Easy pickings: 0 | UI/UX: 0
-------------------------------------+-------------------------------------
Changes (by Nasir Hussain):

* needs_better_patch: 1 => 0


* needs_tests: 1 => 0


--
Ticket URL: <https://code.djangoproject.com/ticket/30758#comment:11>

Django

unread,
Sep 17, 2019, 6:13:40 AM9/17/19
to django-...@googlegroups.com
#30758: DateTimeRangeField with default crashes in django admin (object has no
attribute 'strip').
-------------------------------------+-------------------------------------
Reporter: yeppus | Owner: Nasir
| Hussain
Type: Bug | Status: closed
Component: contrib.postgres | Version: master
Severity: Normal | Resolution: fixed

Keywords: DateTimeRangeField | Triage Stage: Accepted
Has patch: 1 | Needs documentation: 0

Needs tests: 0 | Patch needs improvement: 0
Easy pickings: 0 | UI/UX: 0
-------------------------------------+-------------------------------------
Changes (by Mariusz Felisiak <felisiak.mariusz@…>):

* status: assigned => closed
* resolution: => fixed


Comment:

In [changeset:"faf4b988fe75dd4045bc5c62496cc4f2e0db8c4d" faf4b988]:
{{{
#!CommitTicketReference repository=""
revision="faf4b988fe75dd4045bc5c62496cc4f2e0db8c4d"
Fixed #30758 -- Made RangeFields use multiple hidden inputs for initial
data.
}}}

--
Ticket URL: <https://code.djangoproject.com/ticket/30758#comment:13>

Django

unread,
Sep 17, 2019, 6:13:41 AM9/17/19
to django-...@googlegroups.com
#30758: DateTimeRangeField with default crashes in django admin (object has no
attribute 'strip').
-------------------------------------+-------------------------------------
Reporter: yeppus | Owner: Nasir
| Hussain
Type: Bug | Status: assigned

Component: contrib.postgres | Version: master
Severity: Normal | Resolution:
Keywords: DateTimeRangeField | Triage Stage: Accepted
Has patch: 1 | Needs documentation: 0

Needs tests: 0 | Patch needs improvement: 0
Easy pickings: 0 | UI/UX: 0
-------------------------------------+-------------------------------------

Comment (by Mariusz Felisiak <felisiak.mariusz@…>):

In [changeset:"733dbb21c734920fceb7c285e7396b15db4182ed" 733dbb2]:
{{{
#!CommitTicketReference repository=""
revision="733dbb21c734920fceb7c285e7396b15db4182ed"
Refs #30758 -- Added more tests for postgres.forms.ranges.
}}}

--
Ticket URL: <https://code.djangoproject.com/ticket/30758#comment:12>

Django

unread,
Sep 17, 2019, 6:23:34 AM9/17/19
to django-...@googlegroups.com
#30758: DateTimeRangeField with default crashes in django admin (object has no
attribute 'strip').
-------------------------------------+-------------------------------------
Reporter: yeppus | Owner: Nasir
| Hussain
Type: Bug | Status: closed
Component: contrib.postgres | Version: master
Severity: Normal | Resolution: fixed

Keywords: DateTimeRangeField | Triage Stage: Accepted
Has patch: 1 | Needs documentation: 0

Needs tests: 0 | Patch needs improvement: 0
Easy pickings: 0 | UI/UX: 0
-------------------------------------+-------------------------------------

Comment (by Mariusz Felisiak <felisiak.mariusz@…>):

In [changeset:"685d956764e6c76d1834274f3afa6ef0ce5d85a1" 685d9567]:
{{{
#!CommitTicketReference repository=""
revision="685d956764e6c76d1834274f3afa6ef0ce5d85a1"
[3.0.x] Fixed #30758 -- Made RangeFields use multiple hidden inputs for
initial data.

Backport of faf4b988fe75dd4045bc5c62496cc4f2e0db8c4d from master.
}}}

--
Ticket URL: <https://code.djangoproject.com/ticket/30758#comment:14>

Reply all
Reply to author
Forward
0 new messages