2011-09-19 27 views
35

djangoでこのSQLと同等の処理を行うにはどうしたらいいですか?djangoはサーバの現在時刻にDateTimeFieldを設定します

UPDATE table SET timestamp=NOW() WHERE ... 

特に私は、データベースがクライアント・マシン上で時間にしていない実行していたサーバからシステム時刻を取得するために、サーバの組み込み関数を使用して、日時フィールドを設定します。

生のSQLを直接実行することができますが、データベースには現在の日時を取得するためのさまざまな機能があるため、よりポータブルなソリューションを探しています。

編集:auto_now paramに言及した人はほとんどいません。これは、すべての変更時にdatetimeを更新しますが、datetimeは特定の場合にのみ更新します。

答えて

1

たぶん、あなたは、ドキュメントに見てみる必要があります。
Modelfields: DateField

オプション「auto_now」をあなたが探しているものだけである可能性があります。 DateTimeFieldで使用することもできます。これは、モデルを保存するたびにDateTimeを更新します。したがって、あなたのDateTimeFieldに設定されているオプションでは、データレコードを取得して再度保存して時間を正しく設定することができます。

+0

私はすべての変更の日時を更新する必要はありません。 – kefeizhou

+0

その後、私はjesseのdatetime.now() - ソリューションを推薦します。 – j0ker

47

j0kerと同じように、タイムスタンプの自動更新を希望する場合は、auto_nowオプションを使用してください。例えば。 date_modified = models.DateTimeField(auto_now=True)

また、手動で行う場合は、Python datetime.now()を使用した単純な割り当てではありませんか。

from datetime import datetime 

obj.date_modified = datetime.now() 
+3

Auto_nowは、必要でないすべての更新時にdatetimeフィールドを更新します。そして、Pythonのdatetime.now()は、クライアント側で現在のdatetimeを取得します。これは、サーバー上のdatetimeに近いことが保証されていません。 – kefeizhou

+0

datetime.now()はクライアントのdatetimeをどのように使用しますか?ビュー内のすべてのPythonコードはサーバー上で実行されるため、もちろんサーバーの日時を使用します。 – j0ker

+4

サーバではデータベースをホストするマシンを意味し、クライアントはpython/djangoを実行してデータベースからデータにアクセスするマシンです。ここでは、複数のクライアントマシンがデータベースにアクセスしてタイムスタンプを更新しているときに、クライアントのシステム時刻が同期されていない場合(許可が不十分のために不可能になる場合があります)、エントリが更新されます。これが、タイムスタンプが同じクロックから来るように、サーバー上でシステム時刻を使用する方が良い理由です。 – kefeizhou

2

あなたが外部サーバ(Djangoアプリケーションをホスティングしている、すなわち、ない1)から日時をしたい場合は、使用するdatatimeのためにそれを手動でペグする必要があるとしています。 select now();などのSQLコマンドを使用するか、ssh [email protected] "date +%s"のようなSSH経由のものを使用できます。

+0

これはraw update sqlを直接実行するより複雑です(これは質問に記載されています) – kefeizhou

+0

Djangoが表示しているフォームにSQL Serverの時刻を入れたかったという印象を受けました.Sqlサーバーを設定するだけですかそれは挿入/更新中の自分の時間ですか? –

5

あなたはデータベースの現在の時刻を使用することを表すためにカスタム値を作成するには、このようなものを使用することができます。

class DatabaseDependentValue(object): 
    def setEngine(self, engine): 
     self.engine = engine 

    @staticmethod 
    def Converter(value, *args, **kwargs): 
     return str(value) 

class DatabaseNow(DatabaseDependentValue): 
    def __str__(self): 
     if self.engine == 'django.db.backends.mysql': 
      return 'NOW()' 
     elif self.engine == 'django.db.backends.postgresql': 
      return 'current_timestamp' 
     else: 
      raise Exception('Unimplemented for engine ' + self.engine) 

django_conversions.update({DatabaseNow: DatabaseDependentValue.Converter}) 

def databaseDependentPatch(cls): 
    originalGetDbPrepValue = cls.get_db_prep_value 
    def patchedGetDbPrepValue(self, value, connection, prepared=False): 
     if isinstance(value, DatabaseDependentValue): 
      value.setEngine(connection.settings_dict['ENGINE']) 
      return value 
     return originalGetDbPrepValue(self, value, connection, prepared) 
    cls.get_db_prep_value = patchedGetDbPrepValue 

そしてDateTimeField型にDatabaseNowを使用することができるようにする:

databaseDependentPatch(models.DateTimeField) 

その後、順番に最終的にあなたがきれいに行うことを可能にする:ここでは

class Operation(models.Model): 
    dateTimeCompleted = models.DateTimeField(null=True) 
    # ... 

operation = # Some previous operation 
operation.dateTimeCompleted = DatabaseNow() 
operation.save() 
+1

私にとって、 'django_conversions.update'はそれを機能させるために必須であり、他のいくつかの回答には欠けています。私はDjango 1.6を使用しています。 –

7

ですどのように私はこの問題を解決した。それは誰かの時間を節約できます願っています:

from django.db import models 

class DBNow(object): 
    def __str__(self): 
     return 'DATABASE NOW()' 
    def as_sql(self, qn, val): 
     return 'NOW()', {} 
    @classmethod 
    def patch(cls, field): 
     orig_prep_db = field.get_db_prep_value 
     orig_prep_lookup = field.get_prep_lookup 
     orig_db_prep_lookup = field.get_db_prep_lookup 

     def prep_db_value(self, value, connection, prepared=False): 
      return value if isinstance(value, cls) else orig_prep_db(self, value, connection, prepared) 

     def prep_lookup(self, lookup_type, value): 
      return value if isinstance(value, cls) else orig_prep_lookup(self, lookup_type, value) 

     def prep_db_lookup(self, lookup_type, value, connection, prepared=True): 
      return value if isinstance(value, cls) else orig_db_prep_lookup(self, lookup_type, value, connection=connection, prepared=True) 

     field.get_db_prep_value = prep_db_value 
     field.get_prep_lookup = prep_lookup 
     field.get_db_prep_lookup = prep_db_lookup 

# DBNow Activator 
DBNow.patch(models.DateTimeField) 

そしてちょうど(DBNowを使用)を更新し、フィルタリングが必要とされている値として:

books = Book.objects.filter(created_on__gt=DBNow()) 

    or: 

book.created_on = DBNow() 
book.save() 
+0

あなたのDjangoのバージョンを知っていますか?私はDjango 1.6のプロジェクトでこのサンプルを使用していますが、Djangoはas_sqlの代わりに__str __の戻り値を使用してSQLを構築するため、動作しません。 –

3

私はあなたが可能にPythonのDjangoのプラグインモジュールを作成しました特定のケース(下記usageを参照)とauto_nowauto_now_addカラムの両方で、の使用をDateTimeFieldオブジェクトで制御します。

ジャンゴ-PG-現在のタイムスタンプ

GitHubの:https://github.com/jaytaylor/django-pg-current-timestamp

は、PyPI:https://pypi.python.org/pypi/django-pg-current-timestamp

使用例:

from django_pg_current_timestamp import CurrentTimestamp 

mm = MyModel.objects.get(id=1) 
mm.last_seen_date = CurrentTimestamp() 
mm.save() 
## Resulting SQL: 
##  UPDATE "my_model" SET "last_seen_date" = CURRENT_TIMESTAMP; 

print MyModel.objects.filter(last_seen_date__lt=CURRENT_TIME).count() 

MyModel.objects.filter(id__in=[1, 2, 3]).update(last_seen_date=CURRENT_TIME) 
+0

これは古くなっています。 – Andrade

4

マイ微調整コードsqliteのは、MySQLで動作し、 postgresqlと提案されているソリューションより少しきれいです。

DBCurrentTimestamp.patch(models.DateField, models.TimeField, models.DateTimeField) 

をし、このようにそれを使用します:

class DBCurrentTimestamp: 
    def __str__(self): 
     return 'DATABASE CURRENT_TIMESTAMP()' 

    def as_sql(self, qn, connection): 
     return 'CURRENT_TIMESTAMP', {} 

    @classmethod 
    def patch(cls, *args): 
     def create_tweaked_get_db_prep_value(orig_get_db_prep_value): 
      def get_db_prep_value(self, value, connection, prepared=False): 
       return value if isinstance(value, cls) else orig_get_db_prep_value(self, value, connection, prepared) 

      return get_db_prep_value 

     for field_class in args: 
      field_class.get_db_prep_value = create_tweaked_get_db_prep_value(field_class.get_db_prep_value) 

は、私はこのような私のmodels.pyファイルの末尾@それをアクティブ

self.last_pageview = DBCurrentTimestamp() 
12

受け入れ答えは時代遅れです。ここではそうすることの現在の最も簡単な方法です:

from django.utils import timezone 

timezone.now() 
0

あなたはDjangoの1.9を起動し、データベース機能Nowを使用することができます。

from django.db.models.functions import Now 
Model.objects.filter(...).update(timestamp=Now()) 
関連する問題