2

Tastypie が ManyToMany クエリで適切に動作するのに問題があります。

これが私のモデルの単純化されたバージョンです。

class Buttons(models.Model):
    name = models.CharField(max_length=255)
    deleted = models.IntegerField()
    date_entered = models.DateTimeField(auto_now_add=True)
    date_modified = models.DateTimeField(auto_now=True)
    jacket = models.ManyToManyField('Jackets', through='JacketsButtons', related_name='buttons_jackets', blank=True)

    class Meta:
        app_label = 'habby'
        db_table = u'buttons'

#joining table
class JacketsButtons(models.Model):
    date_modified = models.DateTimeField(auto_now=True)
    deleted = models.IntegerField()
    jacket_id = models.ForeignKey('Jackets')
    button_id = models.ForeignKey('Buttons')
    class Meta:
        app_label = 'habby'
        db_table = u'jacket_buttons'

class Jackets(models.Model):
    name = models.CharField(max_length=450, blank=True)
    deleted = models.IntegerField()
    date_entered = models.DateTimeField(auto_now_add=True)
    date_modified = models.DateTimeField(auto_now=True)

    class Meta:
        app_label = 'habby'
        db_table = u'jackets'

そして、これらはリソース モデルです。

class ButtonsResource(ModelResource):
    jacket = fields.ToManyField('habby.JacketsResource', "jacket", null=True, readonly=True)
    class Meta:
        queryset = Buttons.objects.filter(jacketsbuttons__deleted=0)
        resource_name = 'buttons'
        always_return_data = True
        filtering = {
                "id": ALL,
                "name": ALL,
                "deleted" : ALL,
                "date_entered" : ALL,
                "date_modified" : ALL,
                "jacket" : ALL_WITH_RELATIONS
        }

class JacketsResource(ModelResource):
    class Meta:
        queryset = Jackets.objects.filter(deleted=0)
        resource_name = 'jackets'
        always_return_data = True
        filtering = {
                "id": ALL,
                "name": ALL,
                "deleted" : ALL,
                "date_entered" : ALL,
                "date_modified" : ALL,
        }

今、私がやろうとしているのは、結合テーブルの 1 つのパラメーターとジャケット テーブルの 1 つのパラメーターによってボタンをフィルター処理することです。これは、django で完全に機能します。

Buttons.objects.filter(
        jacket__id="1",
        jacketsbuttons__deleted=0)

しかし、TastyPie で同等のことを行う方法がわかりません。

私はこれを試しました:

GET /api/v1/buttons/?jacket__id=1&jacketsbuttons__deleted=0

しかし TastyPie は、self.fields に見つからないため、Resource.build_filters() で削除されているため、jacketsbuttons__deleted パラメータを無視します。

それで、メタクラスのクエリセットの一部として条件を指定する上で示したセットアップを試しました。これにより、この質問のトピックにたどり着きました。

リソースをクエリして jacket__id を指定すると、クエリセットが完全に無視され、その結果、結合テーブル フィルターが無視されます。

...
class Meta:
            queryset = Buttons.objects.filter(jacketsbuttons__deleted=0)
...

GET /api/v1/buttons/?jacket__id=1

しかし、jacket__id パラメーターを別のネイティブ ボタン パラメーターに置き換えたり、すべてのパラメーターを省略したりすると、正常に機能し、結合テーブル フィルターが正しく使用されます。

GET /api/v1/buttons/?name=round_button

TastyPie Cookbookで提案されているように、「クエリセットへのリクエストごとの変更」も試しましたが、 jacket__idでクエリを実行しようとするとすぐに無視されました。

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

    def get_object_list(self, request):
        return super(ButtonsResource, self).get_object_list(request).filter(jacketsbuttons__deleted=0)

では、なぜ無視されているのでしょうか。どうすれば強制的に使用できますか?

また、これを達成するためのより良い方法を知っている人はいますか?

前もって感謝します。

ジェイド

4

1 に答える 1

1

以前にも同様のシナリオがありましたが、その後、apply_filter 関数を次のように変更しました。

def apply_filters(self, request, applicable_filters):
    """
    accept extra query in request
    """
    query_foo = request.GET.get('foo', None)
    query_bar = request.GET.get('bar', None)
    semi_filtered = super(RouteResource, self).apply_filters(request, applicable_filters)
    if query_foo:
        filtered_objects = semi_filtered.filter(..something with query_foo..)
        return filtered_objects
    else:
        return semi_filtered

この関数がどのように機能するかは、tastypie のリソース コードをいつでも確認できます。それが役に立てば幸い。

于 2013-04-12T14:40:38.083 に答える