Ticket #21523: patch_21523.diff

File patch_21523.diff, 3.8 KB (added by Hugo Rodger-Brown, 11 years ago)

Patch for the fix.

  • django/db/models/fields/__init__.py

    From 9c562eb419e84ee9c681546b7db1feb0d8fb8363 Mon Sep 17 00:00:00 2001
    From: Hugo Rodger-Brown <hugo@rodger-brown.com>
    Date: Thu, 28 Nov 2013 17:49:56 +0000
    Subject: [PATCH] =?UTF-8?q?Fixed=20#21523=20=E2=80=94=20added=20additional=20?=
     =?UTF-8?q?parsing=20to=20DateField=20to=5Fpython=20method.?=
    MIME-Version: 1.0
    Content-Type: text/plain; charset=UTF-8
    Content-Transfer-Encoding: 8bit
    
    The to_python method attempts to convert a DateField value to a python
    datetime.date object instance. It checks for datetime.date, datetime.
    datetime instances, and if neither of those it then attempts to parse
    the value as a string. This can fail if the value is an object that is
    not a date, but is being used to represent one - i.e. a mock object.
    
    Previously there was a call to django.utils.encoding.smart_str before
    the call to parse_date, which essentially converted the value to its
    unicode representation. This was removed when the smart_str method was
    removed (in favour of smart_text). I have put a call to smart_text back
    in.
    ---
     django/db/models/fields/__init__.py         |  9 +++++++++
     tests/regressiontests/model_fields/tests.py | 15 +++++++++++++++
     2 files changed, 24 insertions(+)
    
    diff --git a/django/db/models/fields/__init__.py b/django/db/models/fields/__init__.py
    index 9949dfa..069e565 100644
    a b class DateField(Field):  
    693693        if isinstance(value, datetime.date):
    694694            return value
    695695
     696        # handle objects that are neither dates nor strings, but which
     697        # return a parseable date string, e.g. a mock date class.
     698        value = smart_text(value)
     699
    696700        try:
    697701            parsed = parse_date(value)
    698702            if parsed is not None:
    class DateTimeField(DateField):  
    784788                value = timezone.make_aware(value, default_timezone)
    785789            return value
    786790
     791
     792        # handle objects that are neither dates nor strings, but which
     793        # return a parseable date string, e.g. a mock date class.
     794        value = smart_text(value)
     795
    787796        try:
    788797            parsed = parse_datetime(value)
    789798            if parsed is not None:
  • tests/regressiontests/model_fields/tests.py

    diff --git a/tests/regressiontests/model_fields/tests.py b/tests/regressiontests/model_fields/tests.py
    index a49894e..eb1a5fd6 100644
    a b  
    11from __future__ import absolute_import, unicode_literals
    22
     3import mock
    34import datetime
    45from decimal import Decimal
    56
    class ForeignKeyTests(test.TestCase):  
    127128        b = Bar.objects.create(b="bcd")
    128129        self.assertEqual(b.a, a)
    129130
     131from datetime import date as real_date # used to test mocking dates.
    130132class DateTimeFieldTests(unittest.TestCase):
     133   
     134    class FakeDate(real_date):
     135        "An object that is *not* a date, but which could be parsed as such."
     136        def __new__(cls, *args, **kwargs):
     137            return real_date.__new__(real_date, *args, **kwargs)
     138
    131139    def test_datetimefield_to_python_usecs(self):
    132140        """DateTimeField.to_python should support usecs"""
    133141        f = models.DateTimeField()
    class DateTimeFieldTests(unittest.TestCase):  
    144152        self.assertEqual(f.to_python('01:02:03.999999'),
    145153                         datetime.time(1, 2, 3, 999999))
    146154
     155    @mock.patch('datetime.date', FakeDate)
     156    def test_datefield_to_python_can_be_mocked(self):
     157        """DateField.to_python should support mock dates."""
     158        self.assertEqual(models.DateField().to_python(
     159                DateTimeFieldTests.FakeDate.today()),
     160            datetime.date.today())
     161
    147162class BooleanFieldTests(unittest.TestCase):
    148163    def _test_get_db_prep_lookup(self, f):
    149164        from django.db import connection
Back to Top