web-dev-qa-db-ja.com

Django .order_by()および.latest()を使用したクエリ

私にはモデルがあります:

_class MyModel(models.Model):
   creation_date = models.DateTimeField(auto_now_add = True, editable=False)

   class Meta:
      get_latest_by = 'creation_date'
_

私のビューには次のようなクエリがありました。

_instances = MyModel.objects.all().order_by('creation_date')
_

その後、instances.latest()が必要になりましたが、正しいインスタンスが得られず、実際には最初のインスタンスが得られました。 order_byを_-creation_date_に設定したとき、または実際にクエリからorder_byを削除したときのみ、.latest()が正しいインスタンスを与えました。これは、ビューではなくpython manage.py Shellを使用して手動でテストしたときにも発生します。

だから私が今やったことは、モデルのメタにあり、_order_by = ['creation_date']_をリストしており、クエリでは使用していません。

.latest()は、(date)(time)フィールドに基づいて常に最新のインスタンスを返すと予想していました。クエリで_order_by_を使用すると、.latest()が奇妙に動作するのが正しいかどうかを教えてもらえますか?

39
Heyl1

.latest()は、(date)(time)フィールドに基づいて常に最新のインスタンスを返すと予想していました。

ドキュメント

モデルのMetaが_get_latest_by_を指定している場合、latest()への_field_name_引数を省略できます。 Djangoは、デフォルトで_get_latest_by_で指定されたフィールドを使用します。

つまり、MyModel.objects.latest()を実行すると、日付/時刻フィールドに基づいて最新のインスタンスが取得されます。そして、サンプルデータを使用してコードをテストしたとき、実際にテストしました。

その後、instances.latest()が必要になりましたが、正しいインスタンスが得られず、実際には最初のインスタンスが得られました。

latest()の動作方法を誤解しています。 MyModel.objectsで呼び出されると、tableの最新のインスタンスを返します。 querysetで呼び出された場合、latestthe querysetの最初のオブジェクトを返します。クエリセットは、MyModelのすべてのインスタンスで構成され、_creation_date_によって昇順で並べられています。このクエリセットのlatestfirst row of the querysetを返すのは当然です。これは、たまたまtableの最も古い行です。

理解を深める1つの方法は、latestに対して起動されたクエリを表示することです。

事例1:

_from Django.db import connection
MyModel.objects.latest()
print connection.queries[-1]['sql']
_

これは印刷します:

_SELECT "app_mymodel"."id", "app_mymodel"."creation_date" FROM 
"app_mymodel" ORDER BY "app_mymodel"."creation_date" DESC LIMIT 1
_

_creation_date DESC_およびLIMIT句による順序に注意してください。前者は_get_latest_by_のおかげですが、後者はlatestの貢献です。

次に、ケース2:

_MyModel.objects.order_by('creation_date').latest()
print connection.queries[-1]['sql']
_

プリント

_SELECT "app_mymodel"."id", "app_mymodel"."creation_date" FROM 
"app_mymodel" ORDER BY "app_mymodel"."creation_date" ASC LIMIT 1
_

順序が_creation_date ASC_に変更されていることに注意してください。これは、明示的な_order_by_の結果です。 LIMITはerに付けられ、後でlatestに提供されます。

ケース3:objects.latest()に_field_name_を明示的に指定する場合も参照してください。

_MyModel.objects.latest('id')
print connection.queries[-1]['sql']
_

ショー

_SELECT "app_mymodel"."id", "app_mymodel"."creation_date" FROM "app_mymodel"
ORDER BY "app_mymodel"."id" DESC LIMIT 1
_
69
Manoj Govindan

これは既知の Djangoのバグ で、1.3のリリース後に修正されたと思います。

これは私のために働いた

latestsetuplist = SetupTemplate.objects.order_by('-creationTime')[:10][::1]
0
Manish Gupta