Parcourir la 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 il y a 13 ans
Parent
révision
a4ee82b1ad

+ 4
- 4
oscar/apps/basket/abstract_models.py Voir le fichier

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

+ 2
- 2
oscar/apps/basket/migrations/0003_auto__add_field_line_price_excl_tax.py Voir le fichier

@@ -34,7 +34,7 @@ class Migration(SchemaMigration):
34 34
         },
35 35
         'auth.user': {
36 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 38
             'email': ('django.db.models.fields.EmailField', [], {'max_length': '75', 'blank': 'True'}),
39 39
             'first_name': ('django.db.models.fields.CharField', [], {'max_length': '30', 'blank': 'True'}),
40 40
             'groups': ('django.db.models.fields.related.ManyToManyField', [], {'to': "orm['auth.Group']", 'symmetrical': 'False', 'blank': 'True'}),
@@ -42,7 +42,7 @@ class Migration(SchemaMigration):
42 42
             'is_active': ('django.db.models.fields.BooleanField', [], {'default': 'True'}),
43 43
             'is_staff': ('django.db.models.fields.BooleanField', [], {'default': 'False'}),
44 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 46
             'last_name': ('django.db.models.fields.CharField', [], {'max_length': '30', 'blank': 'True'}),
47 47
             'password': ('django.db.models.fields.CharField', [], {'max_length': '128'}),
48 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 Voir le fichier

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

+ 6
- 5
oscar/apps/dashboard/views.py Voir le fichier

@@ -1,6 +1,7 @@
1
+from datetime import timedelta
1 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 5
 from django.views.generic import TemplateView
5 6
 from django.db.models.loading import get_model
6 7
 from django.db.models import Avg, Sum, Count
@@ -32,7 +33,7 @@ class IndexView(TemplateView):
32 33
         ``Queryset`` of site offers is filtered by end date greater then
33 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 37
                                                offer_type=ConditionalOffer.SITE)
37 38
 
38 39
     def get_active_vouchers(self):
@@ -40,7 +41,7 @@ class IndexView(TemplateView):
40 41
         Get all active vouchers. The returned ``Queryset`` of vouchers
41 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 46
     def get_number_of_promotions(self, abstract_base=AbstractPromotion):
46 47
         """
@@ -78,7 +79,7 @@ class IndexView(TemplateView):
78 79
         when generating the y-axis labels (default=10).
79 80
         """
80 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 83
         start_time = time_now - timedelta(hours=hours-1)
83 84
 
84 85
         orders_last_day = Order.objects.filter(date_placed__gt=start_time)
@@ -125,7 +126,7 @@ class IndexView(TemplateView):
125 126
         return ctx
126 127
 
127 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 131
         orders = Order.objects.filter()
131 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 Voir le fichier

@@ -4,12 +4,15 @@ from south.db import db
4 4
 from south.v2 import SchemaMigration
5 5
 from django.db import models
6 6
 
7
+from django.utils.timezone import now
8
+
9
+
7 10
 class Migration(SchemaMigration):
8 11
 
9 12
     def forwards(self, orm):
10 13
 
11 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 18
     def backwards(self, orm):

+ 3
- 3
oscar/apps/order/abstract_models.py Voir le fichier

@@ -1,9 +1,9 @@
1 1
 from itertools import chain
2 2
 from decimal import Decimal as D
3 3
 import hashlib
4
-import datetime
5 4
 
6 5
 from django.db import models
6
+from django.utils import timezone
7 7
 from django.contrib.auth.models import User
8 8
 from django.template.defaultfilters import slugify
9 9
 from django.utils.translation import ugettext_lazy as _
@@ -240,8 +240,8 @@ class AbstractOrderNote(models.Model):
240 240
     def is_editable(self):
241 241
         if self.note_type == self.SYSTEM:
242 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 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 Voir le fichier

@@ -3,6 +3,8 @@ import datetime
3 3
 from south.db import db
4 4
 from south.v2 import SchemaMigration
5 5
 from django.db import models
6
+from django.utils.timezone import now
7
+
6 8
 
7 9
 class Migration(SchemaMigration):
8 10
 
@@ -11,7 +13,7 @@ class Migration(SchemaMigration):
11 13
         db.rename_column('order_ordernote', 'date', 'date_created')
12 14
 
13 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 19
     def backwards(self, orm):

+ 2
- 2
oscar/apps/order/migrations/0004_auto__add_field_line_upc.py Voir le fichier

@@ -44,7 +44,7 @@ class Migration(SchemaMigration):
44 44
         },
45 45
         'auth.user': {
46 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 48
             'email': ('django.db.models.fields.EmailField', [], {'max_length': '75', 'blank': 'True'}),
49 49
             'first_name': ('django.db.models.fields.CharField', [], {'max_length': '30', 'blank': 'True'}),
50 50
             'groups': ('django.db.models.fields.related.ManyToManyField', [], {'to': "orm['auth.Group']", 'symmetrical': 'False', 'blank': 'True'}),
@@ -52,7 +52,7 @@ class Migration(SchemaMigration):
52 52
             'is_active': ('django.db.models.fields.BooleanField', [], {'default': 'True'}),
53 53
             'is_staff': ('django.db.models.fields.BooleanField', [], {'default': 'False'}),
54 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 56
             'last_name': ('django.db.models.fields.CharField', [], {'max_length': '30', 'blank': 'True'}),
57 57
             'password': ('django.db.models.fields.CharField', [], {'max_length': '128'}),
58 58
             'user_permissions': ('django.db.models.fields.related.ManyToManyField', [], {'to': "orm['auth.Permission']", 'symmetrical': 'False', 'blank': 'True'}),

+ 1
- 1
setup.py Voir le fichier

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

+ 2
- 0
sites/sandbox/settings.py Voir le fichier

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

+ 6
- 13
tests/unit/order/model_tests.py Voir le fichier

@@ -1,7 +1,8 @@
1
+from datetime import timedelta
1 2
 from decimal import Decimal as D
2
-import datetime
3 3
 
4 4
 from django.test import TestCase
5
+from django.utils import timezone
5 6
 import mock
6 7
 
7 8
 from oscar.apps.address.models import Country
@@ -71,15 +72,6 @@ class OrderStatusPipelineTests(TestCase):
71 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 75
 class OrderNoteTests(TestCase):
84 76
 
85 77
     def setUp(self):
@@ -97,9 +89,10 @@ class OrderNoteTests(TestCase):
97 89
         OrderNote.editable_lifetime = 1
98 90
         note = self.order.notes.create(message='test')
99 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 96
             self.assertFalse(note.is_editable())
104 97
 
105 98
 

Chargement…
Annuler
Enregistrer