0

ユーザーによってアップロードされたオブジェクトがあり、いくつかの詳細が含まれていますが、明確にするために、次のモデル表現で簡単に定義できます-

この後、他のユーザーは、このユーザーがアップロードしたものに賛成票と反対票を投じることができるため、投票モデルになります。

ここで、テンプレートに表示されるすべてのオブジェクトの賛成票と反対票を取得したいと考えています。ObjectDetailしたがって、upvote と downvoteという 2 つの関数をクラスに追加します。

このモデルの問題点は、20 個のオブジェクトがあるとします。各オブジェクトに対して 2 つのクエリが実行され、1 つは賛成票を獲得し、もう 1 つは反対票を獲得します。したがって、いいえ。クエリの数は、20 オブジェクトに対して 40 になりました。

これを微調整してクエリの数を減らし、各オブジェクトに賛成票と反対票を表示するにはどうすればよいでしょうか?

class ObjectDetail(models.Model):
    title = models.CharField()
    img = models.ImageField()
    description = models.TextField()
    uploaded_by = models.ForeignKey(User, related_name='voted_by')

    @property
    def upvote(self):
        upvote = Vote.objects.filter(shared_object__id = self.id, 
                             vote_type = True).count()
        return upvote

    @property
    def downvote(self):
        downvote = Vote.objects.filter(shared_object__id = self.id, 
                               vote_type = False).count()
        return downvote

class Vote(models.Model):
    vote_type = models.BooleanField(default = False)
    voted_by =  models.ForeignKey(User, related_name='voted_by')
    voted_for = models.ForeignKey(User, related_name='voted_for')
    shared_object = models.ForeignKey(ObjectDetail, null=True, blank=True)
    dtobject  = models.DateTimeField(auto_now_add=True)
4

2 に答える 2

0

一方では、django は、必要なときに生の SQL を作成する機能を提供します。ただし、この例は単純です。生の SQL を使用してこの情報を取得する必要はありません。

クエリセットの結果にアクセスするまで、Django はクエリの作成を延期します。したがって、クエリセットと Q オブジェクトを使用してクエリ全体を構成し、構成されたクエリの結果にアクセスすることができます。これにより、すべての結果に対して 1 つの DB クエリ (またはインスタンスごとではなくモデルごとに 1 つ) がトリガーされます。

それで、それを行う方法は?特定の ObjectDetail レコード セットのすべての Vote レコードを取得する必要があります。ObjectDetail レコードの ID のリストがあると仮定します。

残念ながら、賛成票と反対票のプロパティは、クエリ セットの「カウント」の結果を返します。これは、「フィルター」呼び出しによって生成されたクエリセットの「結果へのアクセス」としてカウントされます。これらのメソッド定義を、後方関係オブジェクト マネージャーのvote_setを参照するように変更します。

@property
def upvote(self):
    answer = 0
    for vote in self.vote_set.all ():
        if vote.vote_type:
            answer += 1
    return answer

@property
def downvote(self):
    answer = 0
    for vote in self.vote_set.all ():
        if not vote.vote_type:
            answer += 1
    return answer

現在のオブジェクトの投票のクエリ セットにアクセスするだけであることに注意してください。この段階では、orm がキャッシュされた結果にアクセスできると想定しています。

ここで、ビューおよび/またはテンプレートで、大きく複雑なクエリを組み立てたいと考えています。

私の例は機能ビューです:

def home (request):

    # just assigning a constant list for simplicity.
    # Also was lazy and did 10 examples rather than 20.
    objids = [ 1, 5, 15, 23, 48, 52, 55, 58, 59, 60 ]

    # make a bunch of Q objects, one for each object id:
    q_objs = []
    for objid in objids:
        q_objs.append(Q(id__exact = objid))

    # 'or' them together into one big Q object.
    # There's probably a much nicer way to do this.
    big_q = q_objs[0]
    for q_obj in q_objs[1:]:
        big_q |= q_obj

    # Make another queryset that will ask for the Vote objects
    # along with the ObjectDetail objects.
    # Try commenting out this line and uncommenting the one below.
    the_objects = ObjectDetail.objects.filter(big_q).prefetch_related('vote_set')
    # the_objects = ObjectDetail.objects.filter(big_q)

    template = 'home.html'
    context = {
        'the_objects' : the_objects,
        }
    context_instance = RequestContext (request)
    return render_to_response (template, context, context_instance)

関連ドキュメントへのポインタを次に示します。

https://docs.djangoproject.com/en/1.5/topics/db/queries/#querysets-are-lazy https://docs.djangoproject.com/en/1.5/ref/models/querysets/#when-querysets -are-evaluated https://docs.djangoproject.com/en/1.5/topics/db/queries/#complex-lookups-with-q-objects https://docs.djangoproject.com/en/1.5/topics/デシベル/クエリ/#following-relationships-backward

于 2013-07-08T22:41:04.763 に答える