Răsfoiți Sursa

Fixed #24866 -- Added Now() database function

Adam Chainz 9 ani în urmă
părinte
comite
23048d186c

+ 17 - 1
django/db/models/functions.py

@@ -1,7 +1,7 @@
 """
 Classes that represent database functions.
 """
-from django.db.models import IntegerField
+from django.db.models import DateTimeField, IntegerField
 from django.db.models.expressions import Func, Value
 
 
@@ -103,6 +103,22 @@ class Lower(Func):
         super(Lower, self).__init__(expression, **extra)
 
 
+class Now(Func):
+    template = 'CURRENT_TIMESTAMP'
+
+    def __init__(self, output_field=None, **extra):
+        if output_field is None:
+            output_field = DateTimeField()
+        super(Now, self).__init__(output_field=output_field, **extra)
+
+    def as_postgresql(self, compiler, connection):
+        # Postgres' CURRENT_TIMESTAMP means "the time at the start of the
+        # transaction". We use STATEMENT_TIMESTAMP to be cross-compatible with
+        # other databases.
+        self.template = 'STATEMENT_TIMESTAMP()'
+        return self.as_sql(compiler, connection)
+
+
 class Substr(Func):
     function = 'SUBSTRING'
 

+ 15 - 0
docs/ref/models/database-functions.txt

@@ -117,6 +117,21 @@ Usage example::
     >>> print(author.name_lower)
     margaret smith
 
+Now
+---
+
+.. class:: Now()
+
+.. versionadded:: 1.9
+
+Returns the database server's current date and time when the query is executed.
+
+Usage example::
+
+    >>> from django.db.models.functions import Now
+    >>> Article.objects.filter(published__lte=Now())
+    [<Article: How to Django>]
+
 Substr
 ------
 

+ 3 - 0
docs/releases/1.9.txt

@@ -240,6 +240,9 @@ Models
 * Added the :lookup:`date` lookup to :class:`~django.db.models.DateTimeField`
   to allow querying the field by only the date portion.
 
+* Added the :class:`~django.db.models.functions.Now` database function, which
+  returns the current date and time.
+
 CSRF
 ^^^^
 

+ 40 - 1
tests/db_functions/tests.py

@@ -1,8 +1,10 @@
 from __future__ import unicode_literals
 
+from datetime import datetime, timedelta
+
 from django.db.models import CharField, TextField, Value as V
 from django.db.models.functions import (
-    Coalesce, Concat, Length, Lower, Substr, Upper,
+    Coalesce, Concat, Length, Lower, Now, Substr, Upper,
 )
 from django.test import TestCase
 from django.utils import six, timezone
@@ -311,3 +313,40 @@ class FunctionTests(TestCase):
             ],
             lambda a: a.name
         )
+
+    def test_now(self):
+        ar1 = Article.objects.create(
+            title='How to Django',
+            text=lorem_ipsum,
+            written=timezone.now(),
+        )
+        ar2 = Article.objects.create(
+            title='How to Time Travel',
+            text=lorem_ipsum,
+            written=timezone.now(),
+        )
+
+        num_updated = Article.objects.filter(id=ar1.id, published=None).update(published=Now())
+        self.assertEqual(num_updated, 1)
+
+        num_updated = Article.objects.filter(id=ar1.id, published=None).update(published=Now())
+        self.assertEqual(num_updated, 0)
+
+        ar1.refresh_from_db()
+        self.assertIsInstance(ar1.published, datetime)
+
+        ar2.published = Now() + timedelta(days=2)
+        ar2.save()
+        ar2.refresh_from_db()
+        self.assertIsInstance(ar2.published, datetime)
+
+        self.assertQuerysetEqual(
+            Article.objects.filter(published__lte=Now()),
+            ['How to Django'],
+            lambda a: a.title
+        )
+        self.assertQuerysetEqual(
+            Article.objects.filter(published__gt=Now()),
+            ['How to Time Travel'],
+            lambda a: a.title
+        )