Browse Source

Merge pull request #288 from elbaschid/fix/work_with_aware_datetimes

makes Oscar work with aware AND naive datetimes based on USE_TZ
master
David Winterbottom 13 years ago
parent
commit
a4ee82b1ad

+ 4
- 4
oscar/apps/basket/abstract_models.py View File

1
 from decimal import Decimal
1
 from decimal import Decimal
2
 import zlib
2
 import zlib
3
-import datetime
4
 
3
 
5
 from django.db import models
4
 from django.db import models
6
 from django.db.models import query
5
 from django.db.models import query
7
 from django.conf import settings
6
 from django.conf import settings
7
+from django.utils.timezone import now
8
 from django.utils.translation import ugettext as _
8
 from django.utils.translation import ugettext as _
9
 from django.core.exceptions import ObjectDoesNotExist, PermissionDenied
9
 from django.core.exceptions import ObjectDoesNotExist, PermissionDenied
10
 
10
 
199
         for line_to_merge in basket.all_lines():
199
         for line_to_merge in basket.all_lines():
200
             self.merge_line(line_to_merge, add_quantities)
200
             self.merge_line(line_to_merge, add_quantities)
201
         basket.status = MERGED
201
         basket.status = MERGED
202
-        basket.date_merged = datetime.datetime.now()
202
+        basket.date_merged = now()
203
         basket.save()
203
         basket.save()
204
         self._lines = None
204
         self._lines = None
205
 
205
 
220
     def set_as_submitted(self):
220
     def set_as_submitted(self):
221
         """Mark this basket as submitted."""
221
         """Mark this basket as submitted."""
222
         self.status = SUBMITTED
222
         self.status = SUBMITTED
223
-        self.date_submitted = datetime.datetime.now()
223
+        self.date_submitted = now()
224
         self.save()
224
         self.save()
225
 
225
 
226
     def set_as_tax_exempt(self):
226
     def set_as_tax_exempt(self):
386
     @property
386
     @property
387
     def time_since_creation(self, test_datetime=None):
387
     def time_since_creation(self, test_datetime=None):
388
         if not test_datetime:
388
         if not test_datetime:
389
-            test_datetime = datetime.datetime.now()
389
+            test_datetime = now()
390
         return test_datetime - self.date_created
390
         return test_datetime - self.date_created
391
 
391
 
392
     @property
392
     @property

+ 2
- 2
oscar/apps/basket/migrations/0003_auto__add_field_line_price_excl_tax.py View File

34
         },
34
         },
35
         'auth.user': {
35
         'auth.user': {
36
             'Meta': {'object_name': 'User'},
36
             'Meta': {'object_name': 'User'},
37
-            'date_joined': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime(2012, 8, 24, 14, 47, 16, 749550)'}),
37
+            'date_joined': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now'}),
38
             'email': ('django.db.models.fields.EmailField', [], {'max_length': '75', 'blank': 'True'}),
38
             'email': ('django.db.models.fields.EmailField', [], {'max_length': '75', 'blank': 'True'}),
39
             'first_name': ('django.db.models.fields.CharField', [], {'max_length': '30', 'blank': 'True'}),
39
             'first_name': ('django.db.models.fields.CharField', [], {'max_length': '30', 'blank': 'True'}),
40
             'groups': ('django.db.models.fields.related.ManyToManyField', [], {'to': "orm['auth.Group']", 'symmetrical': 'False', 'blank': 'True'}),
40
             'groups': ('django.db.models.fields.related.ManyToManyField', [], {'to': "orm['auth.Group']", 'symmetrical': 'False', 'blank': 'True'}),
42
             'is_active': ('django.db.models.fields.BooleanField', [], {'default': 'True'}),
42
             'is_active': ('django.db.models.fields.BooleanField', [], {'default': 'True'}),
43
             'is_staff': ('django.db.models.fields.BooleanField', [], {'default': 'False'}),
43
             'is_staff': ('django.db.models.fields.BooleanField', [], {'default': 'False'}),
44
             'is_superuser': ('django.db.models.fields.BooleanField', [], {'default': 'False'}),
44
             'is_superuser': ('django.db.models.fields.BooleanField', [], {'default': 'False'}),
45
-            'last_login': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime(2012, 8, 24, 14, 47, 16, 749466)'}),
45
+            'last_login': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now'}),
46
             'last_name': ('django.db.models.fields.CharField', [], {'max_length': '30', 'blank': 'True'}),
46
             'last_name': ('django.db.models.fields.CharField', [], {'max_length': '30', 'blank': 'True'}),
47
             'password': ('django.db.models.fields.CharField', [], {'max_length': '128'}),
47
             'password': ('django.db.models.fields.CharField', [], {'max_length': '128'}),
48
             'user_permissions': ('django.db.models.fields.related.ManyToManyField', [], {'to': "orm['auth.Permission']", 'symmetrical': 'False', 'blank': 'True'}),
48
             'user_permissions': ('django.db.models.fields.related.ManyToManyField', [], {'to': "orm['auth.Permission']", 'symmetrical': 'False', 'blank': 'True'}),

+ 3
- 4
oscar/apps/dashboard/ranges/models.py View File

1
-import datetime
2
 import os
1
 import os
3
 import re
2
 import re
4
 from django.utils.translation import ugettext_lazy as _
3
 from django.utils.translation import ugettext_lazy as _
5
 from django.db import models
4
 from django.db import models
6
-
5
+from django.utils.timezone import now
7
 
6
 
8
 Product = models.get_model('catalogue', 'Product')
7
 Product = models.get_model('catalogue', 'Product')
9
 
8
 
40
         return os.path.basename(self.filepath)
39
         return os.path.basename(self.filepath)
41
 
40
 
42
     def mark_as_failed(self, message=None):
41
     def mark_as_failed(self, message=None):
43
-        self.date_processed = datetime.datetime.now()
42
+        self.date_processed = now()
44
         self.error_message = message
43
         self.error_message = message
45
         self.status = self.FAILED
44
         self.status = self.FAILED
46
         self.save()
45
         self.save()
47
 
46
 
48
     def mark_as_processed(self, num_new, num_unknown, num_duplicate):
47
     def mark_as_processed(self, num_new, num_unknown, num_duplicate):
49
         self.status = self.PROCESSED
48
         self.status = self.PROCESSED
50
-        self.date_processed = datetime.datetime.now()
49
+        self.date_processed = now()
51
         self.num_new_skus = num_new
50
         self.num_new_skus = num_new
52
         self.num_unknown_skus = num_unknown
51
         self.num_unknown_skus = num_unknown
53
         self.num_duplicate_skus = num_duplicate
52
         self.num_duplicate_skus = num_duplicate

+ 6
- 5
oscar/apps/dashboard/views.py View File

1
+from datetime import timedelta
1
 from decimal import Decimal as D, ROUND_UP
2
 from decimal import Decimal as D, ROUND_UP
2
-from datetime import datetime, timedelta
3
 
3
 
4
+from django.utils.timezone import now
4
 from django.views.generic import TemplateView
5
 from django.views.generic import TemplateView
5
 from django.db.models.loading import get_model
6
 from django.db.models.loading import get_model
6
 from django.db.models import Avg, Sum, Count
7
 from django.db.models import Avg, Sum, Count
32
         ``Queryset`` of site offers is filtered by end date greater then
33
         ``Queryset`` of site offers is filtered by end date greater then
33
         the current date.
34
         the current date.
34
         """
35
         """
35
-        return ConditionalOffer.objects.filter(end_date__gt=datetime.now(),
36
+        return ConditionalOffer.objects.filter(end_date__gt=now(),
36
                                                offer_type=ConditionalOffer.SITE)
37
                                                offer_type=ConditionalOffer.SITE)
37
 
38
 
38
     def get_active_vouchers(self):
39
     def get_active_vouchers(self):
40
         Get all active vouchers. The returned ``Queryset`` of vouchers
41
         Get all active vouchers. The returned ``Queryset`` of vouchers
41
         is filtered by end date greater then the current date.
42
         is filtered by end date greater then the current date.
42
         """
43
         """
43
-        return Voucher.objects.filter(end_date__gt=datetime.now())
44
+        return Voucher.objects.filter(end_date__gt=now())
44
 
45
 
45
     def get_number_of_promotions(self, abstract_base=AbstractPromotion):
46
     def get_number_of_promotions(self, abstract_base=AbstractPromotion):
46
         """
47
         """
78
         when generating the y-axis labels (default=10).
79
         when generating the y-axis labels (default=10).
79
         """
80
         """
80
         # Get datetime for 24 hours agao
81
         # Get datetime for 24 hours agao
81
-        time_now = datetime.now().replace(minute=0, second=0)
82
+        time_now = now().replace(minute=0, second=0)
82
         start_time = time_now - timedelta(hours=hours-1)
83
         start_time = time_now - timedelta(hours=hours-1)
83
 
84
 
84
         orders_last_day = Order.objects.filter(date_placed__gt=start_time)
85
         orders_last_day = Order.objects.filter(date_placed__gt=start_time)
125
         return ctx
126
         return ctx
126
 
127
 
127
     def get_stats(self):
128
     def get_stats(self):
128
-        datetime_24hrs_ago = datetime.now() - timedelta(hours=24)
129
+        datetime_24hrs_ago = now() - timedelta(hours=24)
129
 
130
 
130
         orders = Order.objects.filter()
131
         orders = Order.objects.filter()
131
         orders_last_day = orders.filter(date_placed__gt=datetime_24hrs_ago)
132
         orders_last_day = orders.filter(date_placed__gt=datetime_24hrs_ago)

+ 4
- 1
oscar/apps/offer/migrations/0005_auto__add_field_range_date_created.py View File

4
 from south.v2 import SchemaMigration
4
 from south.v2 import SchemaMigration
5
 from django.db import models
5
 from django.db import models
6
 
6
 
7
+from django.utils.timezone import now
8
+
9
+
7
 class Migration(SchemaMigration):
10
 class Migration(SchemaMigration):
8
 
11
 
9
     def forwards(self, orm):
12
     def forwards(self, orm):
10
 
13
 
11
         # Adding field 'Range.date_created'
14
         # Adding field 'Range.date_created'
12
-        db.add_column('offer_range', 'date_created', self.gf('django.db.models.fields.DateTimeField')(auto_now_add=True, default=datetime.datetime(2012, 5, 2, 22, 10, 11, 993563), blank=True), keep_default=False)
15
+        db.add_column('offer_range', 'date_created', self.gf('django.db.models.fields.DateTimeField')(auto_now_add=True, default=now(), blank=True), keep_default=False)
13
 
16
 
14
 
17
 
15
     def backwards(self, orm):
18
     def backwards(self, orm):

+ 3
- 3
oscar/apps/order/abstract_models.py View File

1
 from itertools import chain
1
 from itertools import chain
2
 from decimal import Decimal as D
2
 from decimal import Decimal as D
3
 import hashlib
3
 import hashlib
4
-import datetime
5
 
4
 
6
 from django.db import models
5
 from django.db import models
6
+from django.utils import timezone
7
 from django.contrib.auth.models import User
7
 from django.contrib.auth.models import User
8
 from django.template.defaultfilters import slugify
8
 from django.template.defaultfilters import slugify
9
 from django.utils.translation import ugettext_lazy as _
9
 from django.utils.translation import ugettext_lazy as _
240
     def is_editable(self):
240
     def is_editable(self):
241
         if self.note_type == self.SYSTEM:
241
         if self.note_type == self.SYSTEM:
242
             return False
242
             return False
243
-        return (datetime.datetime.now() - self.date_updated).seconds < self.editable_lifetime
244
-
243
+        delta = timezone.now() - self.date_updated
244
+        return delta.seconds < self.editable_lifetime
245
 
245
 
246
 class AbstractCommunicationEvent(models.Model):
246
 class AbstractCommunicationEvent(models.Model):
247
     """
247
     """

+ 3
- 1
oscar/apps/order/migrations/0003_auto__del_field_ordernote_date__add_field_ordernote_date_created__add_.py View File

3
 from south.db import db
3
 from south.db import db
4
 from south.v2 import SchemaMigration
4
 from south.v2 import SchemaMigration
5
 from django.db import models
5
 from django.db import models
6
+from django.utils.timezone import now
7
+
6
 
8
 
7
 class Migration(SchemaMigration):
9
 class Migration(SchemaMigration):
8
 
10
 
11
         db.rename_column('order_ordernote', 'date', 'date_created')
13
         db.rename_column('order_ordernote', 'date', 'date_created')
12
 
14
 
13
         # Adding field 'OrderNote.date_updated'
15
         # Adding field 'OrderNote.date_updated'
14
-        db.add_column('order_ordernote', 'date_updated', self.gf('django.db.models.fields.DateTimeField')(auto_now=True, default=datetime.datetime(2012, 4, 25, 12, 11, 37, 946052), blank=True), keep_default=False)
16
+        db.add_column('order_ordernote', 'date_updated', self.gf('django.db.models.fields.DateTimeField')(auto_now=True, default=now(), blank=True), keep_default=False)
15
 
17
 
16
 
18
 
17
     def backwards(self, orm):
19
     def backwards(self, orm):

+ 2
- 2
oscar/apps/order/migrations/0004_auto__add_field_line_upc.py View File

44
         },
44
         },
45
         'auth.user': {
45
         'auth.user': {
46
             'Meta': {'object_name': 'User'},
46
             'Meta': {'object_name': 'User'},
47
-            'date_joined': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime(2012, 5, 16, 10, 6, 17, 973689)'}),
47
+            'date_joined': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now'}),
48
             'email': ('django.db.models.fields.EmailField', [], {'max_length': '75', 'blank': 'True'}),
48
             'email': ('django.db.models.fields.EmailField', [], {'max_length': '75', 'blank': 'True'}),
49
             'first_name': ('django.db.models.fields.CharField', [], {'max_length': '30', 'blank': 'True'}),
49
             'first_name': ('django.db.models.fields.CharField', [], {'max_length': '30', 'blank': 'True'}),
50
             'groups': ('django.db.models.fields.related.ManyToManyField', [], {'to': "orm['auth.Group']", 'symmetrical': 'False', 'blank': 'True'}),
50
             'groups': ('django.db.models.fields.related.ManyToManyField', [], {'to': "orm['auth.Group']", 'symmetrical': 'False', 'blank': 'True'}),
52
             'is_active': ('django.db.models.fields.BooleanField', [], {'default': 'True'}),
52
             'is_active': ('django.db.models.fields.BooleanField', [], {'default': 'True'}),
53
             'is_staff': ('django.db.models.fields.BooleanField', [], {'default': 'False'}),
53
             'is_staff': ('django.db.models.fields.BooleanField', [], {'default': 'False'}),
54
             'is_superuser': ('django.db.models.fields.BooleanField', [], {'default': 'False'}),
54
             'is_superuser': ('django.db.models.fields.BooleanField', [], {'default': 'False'}),
55
-            'last_login': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime(2012, 5, 16, 10, 6, 17, 973579)'}),
55
+            'last_login': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now'}),
56
             'last_name': ('django.db.models.fields.CharField', [], {'max_length': '30', 'blank': 'True'}),
56
             'last_name': ('django.db.models.fields.CharField', [], {'max_length': '30', 'blank': 'True'}),
57
             'password': ('django.db.models.fields.CharField', [], {'max_length': '128'}),
57
             'password': ('django.db.models.fields.CharField', [], {'max_length': '128'}),
58
             'user_permissions': ('django.db.models.fields.related.ManyToManyField', [], {'to': "orm['auth.Permission']", 'symmetrical': 'False', 'blank': 'True'}),
58
             'user_permissions': ('django.db.models.fields.related.ManyToManyField', [], {'to': "orm['auth.Permission']", 'symmetrical': 'False', 'blank': 'True'}),

+ 1
- 1
setup.py View File

27
       install_requires=[
27
       install_requires=[
28
           'django>=1.4',
28
           'django>=1.4',
29
           'PIL==1.1.7',
29
           'PIL==1.1.7',
30
-          'South==0.7.3',
30
+          'South==0.7.6',
31
           'django-extra-views==0.2.0',
31
           'django-extra-views==0.2.0',
32
           'django-haystack==2.0.0-beta',
32
           'django-haystack==2.0.0-beta',
33
           'django-treebeard==1.61',
33
           'django-treebeard==1.61',

+ 2
- 0
sites/sandbox/settings.py View File

5
 location = lambda x: os.path.join(
5
 location = lambda x: os.path.join(
6
     os.path.dirname(os.path.realpath(__file__)), x)
6
     os.path.dirname(os.path.realpath(__file__)), x)
7
 
7
 
8
+USE_TZ = True
9
+
8
 DEBUG = True
10
 DEBUG = True
9
 TEMPLATE_DEBUG = True
11
 TEMPLATE_DEBUG = True
10
 SQL_DEBUG = True
12
 SQL_DEBUG = True

+ 6
- 13
tests/unit/order/model_tests.py View File

1
+from datetime import timedelta
1
 from decimal import Decimal as D
2
 from decimal import Decimal as D
2
-import datetime
3
 
3
 
4
 from django.test import TestCase
4
 from django.test import TestCase
5
+from django.utils import timezone
5
 import mock
6
 import mock
6
 
7
 
7
 from oscar.apps.address.models import Country
8
 from oscar.apps.address.models import Country
71
             self.assertEqual('SHIPPED', line.status)
72
             self.assertEqual('SHIPPED', line.status)
72
 
73
 
73
 
74
 
74
-class MockDateTime(datetime.datetime):
75
-
76
-    @classmethod
77
-    def stub(cls, method_name, return_value):
78
-        mocked_method = mock.Mock()
79
-        mocked_method.return_value = return_value
80
-        setattr(cls, method_name, mocked_method)
81
-
82
-
83
 class OrderNoteTests(TestCase):
75
 class OrderNoteTests(TestCase):
84
 
76
 
85
     def setUp(self):
77
     def setUp(self):
97
         OrderNote.editable_lifetime = 1
89
         OrderNote.editable_lifetime = 1
98
         note = self.order.notes.create(message='test')
90
         note = self.order.notes.create(message='test')
99
         self.assertTrue(note.is_editable())
91
         self.assertTrue(note.is_editable())
100
-        now = datetime.datetime.now()
101
-        with mock.patch('datetime.datetime', MockDateTime) as mock_datetime:
102
-            mock_datetime.stub('now', now + datetime.timedelta(seconds=30))
92
+
93
+        now = timezone.now()
94
+        with mock.patch.object(timezone, 'now') as mock_timezone:
95
+            mock_timezone.return_value = now + timedelta(seconds=30)
103
             self.assertFalse(note.is_editable())
96
             self.assertFalse(note.is_editable())
104
 
97
 
105
 
98
 

Loading…
Cancel
Save