3

あまり複雑ではないように見える何かで少しブロックされています。ここに私のモデル:

class Team(models.Model):
    name = models.CharField('team name', max_length=200, unique=True)

class QualityStream(models.Model):
    name = models.CharField('quality stream name', max_length=200, unique=True)
    team = models.ManyToManyField(Team)

class Milestone(models.Model):
    name = models.CharField('milestone name', max_length=200)
    quality_stream = models.ForeignKey(QualityStream)
    team = models.ForeignKey(Team)

ご覧のとおり、チームはいくつかの事前定義された品質ストリームと、実際に品質ストリームに属する達成すべきいくつかのマイルストーンを持つことができます。

ここに私の見解:

<p>{{team.name}}</p>

{% for stream in team.qualitystream_set.all %}
    <p>{{stream.name}}</p>
    {% for milestone in team.milestone_set.all %}

        {% if milestone.quality_stream.id == stream.id  %}
           <p>{{milestone.name}}</p>               
        {% endif %}

    {% endfor %}    
{% endfor %}

アイデアは、チーム、チームに関連付けられた品質ストリーム、および品質ストリームごとにグループ化された各マイルストーンを表示することです。

Team

  Quality Stream 1
     Milestone 1 for Quality Stream 1
     Milestone 2 for Quality Stream 1
  Quality Stream 2
     Milestone 1 for Quality Stream 2
     Milestone 2 for Quality Stream 2

コードは問題なく動作しますが、各品質ストリームのすべてのマイルストーンをループするのはあまり快適ではありません。これを達成するためのより良い方法があるに違いないと思います。何か案は?

4

2 に答える 2

2

あなたがしていることに何の問題もありませんが、特に select_related() を使用してビューでクエリを実行することにより、データベースの最適化が行われる可能性があります。

https://docs.djangoproject.com/en/1.5/topics/db/optimization/#retrieve-everything-at-once-if-you-know-you-will-need-it

また、モデルに多数のフィールドがあり、そのうちのいくつかだけが必要な場合は、only() または defer() を使用できます。大きなフィールドを避けるために defer を使用すると、大幅なパフォーマンスの向上が見られました。only() は defer() の逆です。

https://docs.djangoproject.com/en/1.5/ref/models/querysets/#defer

あなたのモデルはそれほど複雑ではないように見えるので、 select_related() を使用するだけでうまくいくと思います。最適化の決定には、 Django デバッグ ツールバーを使用することを強くお勧めします。デバッグ ツールバーには、実際の select ステートメントと、それぞれにかかった時間が表示されます。最適化に多くの時間を費やす前に、本当に問題があるかどうかを知ることは良いことです。

お役に立てれば

于 2013-03-16T20:35:17.640 に答える
2

あなたのように複数の下降ループをしなければならないと思うときはいつでも、反対側から問題にアプローチできるかどうかを考えてください.

@Pathetique が指摘したように、次のリンクは、実行するクエリの数を最小限に抑える方法を示しています。

https://docs.djangoproject.com/en/1.5/topics/db/optimization/#retrieve-everything-at-once-if-you-know-you-will-need-it

そのリンクのハイライトは、select_relatedでのみ動作するものForeignKeysと、prefetch_relatedでのみ動作するものManyToManyFieldsです。

「一連のチームがあり、これらのチームに関連付けられたすべてのデータを表示したい」という観点からこの問題に取り組んでいたため、 または がないため、利用可能な最適化を使用できませTeamん。ForeignKeysManyToManyFields

代わりに、「すべてのマイルストーンをチームごとにグループ化し、次に品質ストリームごとにグループ化して表示したい」のように問題に取り組むことができます。Milestone クラスは必要なすべてのデータにアクセスできるため、単一のクエリを生成するだけで、クエリセットの作成が非常に簡単になります。

def my_view(request):
    queryset = Milestone.objects.select_related(
        'team', 'quality_stream'
    ).order_by(
        'team__name', 'quality_stream__name'
    ) # a single query to fetch all teams + streams + milestones

    return render_to_response('/your/template.html', 
        { 'milestones':queryset },
        context_instance=RequestContext(request)
    )

今、あなたのテンプレートはあなたが構築した方法を破ろうとしています. ここで、前に述べた問題の定義の出番です。すべてのマイルストーンがありますが、それらをチームごとにグループ化し、次に品質ストリームごとにグループ化します。クエリセットの順序付けは、すべてのマイルストーンを反復処理して、新しいチームまたは新しい品質ストリームに対応しているかどうかを確認できるため、今では役に立ちます。

# your template
{% for milestone in milestones %}
    {% ifchanged %} <p> {{ milestone.team.name }} </p> {% endifchanged %}
    {% ifchanged %} <p> {{ milestone.quality_stream.name }} </p> {% endifchanged %}
    <p> {{ milestone.name }} </p>
{% endfor %}

上記のテンプレートはifchangedテンプレート タグを使用していますが、これはまさにこの目的のために設計されているようです。

于 2013-03-17T00:15:06.387 に答える