7

Tastypieリソースで、クエリセットに注釈を付けていますが、注釈がJSONに流れてTastypieが生成して返すのがわかりません。コードは単純です:

class CompetitionResource(ModelResource):
    total_tickets = fields.IntegerField(readonly=True)

    class Meta:
        queryset = Competition.objects.all().annotate(total_tickets=Count('ticket__ticketownership__user__id', distinct=True))

クエリセットで生成して注釈を付けているそのカウントは、最終的なJSONには表示されません。最終的なJSONにはtotal_usersフィールドがあります(ModelResourceで宣言したため)が、nullです。このような注釈が確実に通過するようにするために、明らかな何かが欠けていますか?そうでない場合、これを解決する方法は何でしょうか?

これを行う1つの方法は、モデルに属性を作成してから、ModelResourceのtotal_usersフィールドをその属性に関連付けることです。しかし、それはおそらく、データベースから取得した個々の競争ごとにカウントクエリを生成することになり、それは良くありません。1つのアノテーションタイプのクエリで実行したいと思います。

4

3 に答える 3

5

はい、分かりました。ModelResourceに追加できるカスタムdehydrate_[フィールド名]メソッドを使用するだけです。Tastypieは、ModelResourceフィールドごとに、dehydrate_ [field name]メソッドを指定したかどうかを確認し、指定した場合は、オブジェクトをバンドルに処理するときにそのメソッドを呼び出します(JSONまたはXMLなどとして出力されます)。このdehydrate_[fieldname]メソッドは、その特定のオブジェクトについて、その時点までにTastypieが作成したバンドルを取得します。このバンドルには、bundle.objの下に元のオブジェクトが含まれているのが良い点です。そして、そのオブジェクトには、get_object_listで指定した元の注釈が引き続き含まれます(上記の回答に示されているように)。したがって、次のコードを使用できます。

class CompetitionResource(ModelResource):
    total_tickets = fields.IntegerField(readonly=True)

    class Meta:
        queryset = Competition.objects.all()

    def get_object_list(self, request):
        return super(CompetitionResource, self).get_object_list(request).annotate(total_tickets=Count('ticket__ticketownership__user__id', distinct=True))

    def dehydrate_total_tickets(self, bundle):
        return bundle.obj.total_tickets

カスタムdehydrate_[fieldname]メソッドから返すものはすべて、そのフィールドの最終値としてそのオブジェクトのバンドルに適切に格納され、適切に処理されて出力されます。

于 2012-09-18T14:02:25.617 に答える
0

ドキュメントには記載されていませんが、ソースを見ると、フィールド宣言に渡すことができる属性引数があり、これを使用してモデルインスタンスの属性に関連付けることができます。

オプションでattribute、を受け入れます。これは、インスタンス属性の文字列であるか、の間にオブジェクトから呼び出し可能であるか、の間に dehydrateデータをオブジェクトにプッシュする必要がありますhydrate。デフォルトはNone、です。これは、データに手動でアクセスすることを意味します。

したがって、あなたの例では、次の方法でうまくいくはずです。

class CompetitionResource(ModelResource):
    total_tickets = fields.IntegerField(readonly=True, attribute='total_tickets')

    class Meta:
        queryset = Competition.objects.all().annotate(total_tickets=Count('ticket__ticketownership__user__id', distinct=True))

脱水ソリューションは、送信されたオブジェクトに値を入力するために機能しますが、組み込みのフィルタリング(および並べ替え)など、Tastypieの他の機能の一部を簡単に利用することはできません。属性引数でフィールド定義を使用すると、そうなります。

于 2018-07-12T16:58:16.097 に答える
-1

私はあなたの問題がTastypieのドキュメントで与えられた警告に関連しているかもしれないと思いますqueryset

これに呼び出し可能オブジェクトを配置すると、それらは1回だけ評価されます(Metaクラスがインスタンス化されるとき)。これは特に日付/時刻に関連するものに影響します。これを回避する方法については、:ref:cookbookを参照してください。

クックブックの関連セクションを見ると、次のようなものを試してみるべきだと思います。

class CompetitionResource(ModelResource):
    total_users = fields.IntegerField(readonly=True)

    class Meta:
        queryset = Competition.objects.all()

    def get_object_list(self, request):
        return super(CompetitionResource, self).get_object_list(request).annotate(total_tickets=Count('ticket__ticketownership__user__id', distinct=True))
于 2012-09-17T18:22:39.647 に答える