Djangoのクエリセットから最初のオブジェクトを取得するか、存在しない場合はNone
を返したいと思うことがよくあります。これを行うには多くの方法がありますが、すべてうまくいきます。しかし、私はどちらが最もパフォーマンスが高いのだろうかと思っています。
qs = MyModel.objects.filter(blah = blah)
if qs.count() > 0:
return qs[0]
else:
return None
これにより、2つのデータベース呼び出しが発生しますか?それはもったいないようです。これは速いですか?
qs = MyModel.objects.filter(blah = blah)
if len(qs) > 0:
return qs[0]
else:
return None
別のオプションは次のとおりです。
qs = MyModel.objects.filter(blah = blah)
try:
return qs[0]
except IndexError:
return None
これにより、単一のデータベース呼び出しが生成されます。これは適切です。ただし、例外オブジェクトを長時間作成する必要があります。これは、本当に必要なのが些細なifテストだけである場合に実行する非常にメモリ集約的な作業です。
単一のデータベース呼び出しだけで、例外オブジェクトでメモリを乱すことなくこれを行うにはどうすればよいですか?
Django 1.6(2013年11月リリース) 導入 便利なメソッドfirst()
およびlast()
は、結果の例外を飲み込み、クエリセットがオブジェクトを返さない場合にNone
を返します。
正解は
Entry.objects.all()[:1].get()
以下で使用できます
Entry.objects.filter()[:1].get()
すべてのレコードの完全なデータベース呼び出しを強制するため、最初にリストに変換したくないでしょう。上記を実行するだけで、最初のものだけがプルされます。 .order_by
を使用して、必要なものを最初に取得することもできます。
.get()
を必ず追加してください。追加しないと、オブジェクトではなくQuerySetが返されます。
r = list(qs[:1])
if r:
return r[0]
return None
現在、Django 1.9には、クエリセット用のfirst()
メソッドがあります。
YourModel.objects.all().first()
これは、.get()
や[0]
よりも優れた方法です。クエリセットが空の場合は例外をスローしないため、exists()
を使用して確認する必要はありません。
最初の要素を頻繁に取得する場合は、QuerySetを次の方向に拡張できます。
class FirstQuerySet(models.query.QuerySet):
def first(self):
return self[0]
class ManagerWithFirstQuery(models.Manager):
def get_query_set(self):
return FirstQuerySet(self.model)
次のようなモデルを定義します。
class MyModel(models.Model):
objects = ManagerWithFirstQuery()
そして、次のように使用します。
first_object = MyModel.objects.filter(x=100).first()
こんな感じ
obj = model.objects.filter(id=emp_id)[0]
または
obj = model.objects.latest('id')
これも機能します:
def get_first_element(MyModel):
my_query = MyModel.objects.all()
return my_query[:1]
空の場合は空のリストを返し、そうでない場合はリスト内の最初の要素を返します。
既存のようなDjangoメソッドを使用する必要があります。それを使用するためにそこに。
if qs.exists():
return qs[0]
return None
Django 1.6以降では、次のようにfirst()メソッドでfilter()を使用できます。
Model.objects.filter(field_name=some_param).first()