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,
        }

现在,我要做的是过滤按钮,通过连接表上的一个参数和夹克表上的一个参数,这在 django 中完美运行:

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

但我不知道如何在 TastyPie 中做同样的事情。

我试过这个:

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

但是 TastyPie 忽略了 jacksbuttons__deleted 参数,因为它在 Resource.build_filters() 中被删除,因为它在 self.fields 中找不到。

因此,我尝试了上面显示的设置,其中我将条件指定为元类中查询集的一部分,这让我想到了这个问题的主题。

当查询资源并指定jacket__id 时,它完全忽略查询集,因此,连接表过滤器。

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

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

但是,当我将 jack__id 参数替换为另一个本机按钮参数时,或者甚至省略所有参数时,它都可以正常工作,连接表过滤器使用正确。

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

我还按照TastyPie Cookbook中的建议尝试了“查询集的每个请求更改” ,但是当我尝试通过 jack__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

您可以随时查看美味派的资源代码以了解此功能的工作原理。希望能帮助到你。

于 2013-04-12T14:40:38.083 回答