4

私はトリッキーな Django クエリを見つけようとしています。あなたが助けてくれることを願っています。私はこのモデルを持っています:

class ActiveVenue(models.Model):
    event = models.ForeignKey(Event)
    venue = models.ForeignKey(Venue)

class Venue(models.Model):
    name = models.CharField(max_length=200)

class Event(models.Model):
    user = models.ForeignKey(User)
    name = models.CharField(max_length=200)

私のアプリには多くのイベントがあり、各イベントは複数のアクティブな会場を持つことができるため、現在のデータ構造です。これはすでに展開されたサイトであり、現在のモデル構造を維持したいので、解決策が「モデルを foo に変更する」ではないことをお勧めします。

最も人気のある会場を返すクエリを作成したいと考えていますが、その会場はユーザーごとに 1 回だけカウントされます。例として、4 つのイベントを持つ 1 人のユーザーがいて、毎回同じ会場を使用している場合、最も人気のある会場を決定するときに、その会場を 1 回だけカウントしたいと考えています。

これを説明するために、これが私のデータだと想像してください。

event: A    user: bob   venue: The Hill
event: B    user: bob   venue: The Hill
event: C    user: bob   venue: The Hill
event: D    user: jane   venue: The Oaks
event: E    user: sarah   venue: The Pound
event: F    user: david   venue: The Pound
event: G    user: ron   venue: The Oaks
event: H    user: erica   venue: The Oaks

ここで一般的な順序は次のとおりです。

1. The Oaks
2. The Pound
3. The Hill

postgres と sqlite の両方で機能する (つまり、依存しないdistinct()(sqlite ではサポートされていない)) これを行うためのクエリを作成する方法について何か提案はありますか?

ありがとう!

4

4 に答える 4

1

これは機能しますか?

from collections import Counter 
results = Counter([vid for vid, eid in ActiveVenue.objects.values_list("venue_id", "event_id").distinct()]
于 2013-03-26T06:07:07.090 に答える
0

このようなものが機能するかどうかを確認してください

ActiveVenue.objects.all().annotate(score=Count('event__user', distinct=True)).order_by('-score')
于 2013-03-26T06:30:32.210 に答える
0

これは私のバージョンです(テストを終了):

models.py

class Venue(models.Model):
    name = models.CharField(max_length=200)

    def __unicode__(self):
        return self.name

    def ranking(self):
        count=0
        actives = ActiveVenue.objects.filter(
            venue__name=self.name).values(
            'event__user__username', 'venue__name').distinct()
        for active in actives:
            count += 1
        return count

ビュー.py

def getRanking( anObject ):
    return anObject.ranking()

def myview(request):
    venues = list(Venue.objects.filter())
    venues.sort(key=getRanking, reverse=True)
    return render(request,'page.html',{'venues': venues})

テンプレート

{% for venue in venues %}
    {{forloop.counter}}. {{venue}}<br/>
{% endfor %}

出力:

  1. オークス
  2. ポンド
  3. ザ・ヒル
于 2013-03-26T06:40:30.997 に答える
0

ここに問題に対する私の見解があります。まず、関連するユーザーに対応する会場 ID とスコアを取得するクエリを次に示します。

testquery = ActiveVenue.objects.values("venue").annotate(score=Count("event__user", distinct=True)).order_by("-score")

結果

[{'score': 3, 'venue': 2}, {'score': 2, 'venue': 3}, {'score': 1, 'venue': 1}]

次に、会場 ID が新しいリストに配置されます。

query_ids = [item["venue"] for item in testquery]
[2, 3, 1]

次に、対応する Venue オブジェクトを取得する必要があります。

tempresult = Venue.objects.filter(id__in=query_ids)
[<Venue: The Hill>, <Venue: The Oaks>, <Venue: The Pound>

最後に、以前に取得したスコアに基づいて Venue オブジェクトを並べ替えるために、リスト内包表記が実行されます。

result = [venue for venue_id in query_ids for venue in tempresult if venue_id == venue.id]
[<Venue: The Oaks>, <Venue: The Pound>, <Venue: The Hill>]

これにより、テスト データに基づく適切な結果が得られます。

于 2013-04-01T20:44:48.580 に答える