2017-08-17 5 views
0

私は名前と年齢を持つ非常に基本的なユーザモデルがあるとします。Django:N + 1要求なしでクエリーセットの各要素にカスタム属性を追加する方法は?

class User(models.Model): 
    name = CharField() # e.g. John Smith 
    age = IntegerField() # e.g. 21 

私は、ユーザー18+ Y/Oをフィルタリングすると、それらのそれぞれが"John Smith"のために、例えば(特別な属性namesakesを追加するためにそれ["John Williams", "John for Neumann", ...]のようなものです)。

for user in User.objects.filter(age__gt=18): 
    user.namesakes = User.objects.filter(name__startswith=user.name.split()).\ 
            all() 

をしかし、どのように私は1つっぽいのリクエストでこれを行うのです:私が知っている

、どのようにN + 1つのリクエストでこれを行うには?理想的には、クエリーセット内の各Userオブジェクトに対して、名前付きクエリーセットを含むカスタム属性namesakesを作成したいと考えています。これはannotate()またはprefetch_related() with to_attrの場合と非常によく似ていますが、正確ではありません。

可能であれば、生のSQLを使用しないことをお勧めします。

ありがとうございます。

+0

私が見ることができる最も近いのは[自分のF式を行うことに関するこの回答](https://stackoverflow.com/a/28821724/1081569)でした。 SQL関数と組み合わせて、[Postgres 'substring(string from pattern)'や 'split_part'](https://www.postgresql.org/docs/9.6/static/functions-string)のように文字列を分割することができます。 html)、おそらくあなたはそれを行うことができます。これはデータベース固有のものかもしれませんが、避けたい(生のSQLはありません)が、Djangoの文字列を分割する機能は見ていません。 –

+0

@PauloAlmeidaありがとう、パウロ、私はそれがまさに私が必要と思うものだと思う。 –

答えて

1

私は私が必要なものと非常によく似た何かを、blog postを発見し、....親愛なる神...それでも

>>> from django.db.models import F, Q, Case, IntegerField, Sum, Value, When 
>>> from django.db.models.functions import Coalesce 
>>> pizzas = Pizza.objects.annotate(
...  uses_name_of_another_pizza_as_name_prefix=Coalesce(
...   Sum(
...    Case(
...     When(
...      Q(
...       ~Q(pk=F('category__pizzas')) & 
...       Q(name__startswith=F('category__pizzas__name')) 
...     ), 
...      then=Value(1) 
...    ), 
...     output_field=IntegerField(), 
...   ), 
...  ), 
...   0, 
... ), 
...) 
>>> [p, p.uses_name_of_another_pizza_as_name_prefix for p in pizzas] 
[ 
    (<Pizza: Hawaiian>, 0), 
    (<Pizza: Hawaiian King>, 1), 
    (<Pizza: Pepperoni>, 0), 
] 

、それは私が正確に必要なものはできません。だから、私は生のSQLと一緒に行くことを好みました。

+0

ニース!私は 'Concat'でいくつかのことを見ていましたが、' Coalesce'ではありませんでした。つまり、私が正しく理解すれば、あなたのユースケースでは、Johnの名前を探すためにDB(姓のついていない)に「John」が必要でしょうか? –

+0

@PauloAlmeidaええと、この投稿は私の問題を完全に解決するものではありません。名前の由来は数えますが、リストは返されません。 「合体」は本当に大きな役割を果たすわけではありません。それは単にデフォルトを提供するだけです。私はまだ残念ながら私の自己結合を行う良い方法を見つけていない:) –

関連する問題