【问题标题】:Get around Tastypie ignoring queryset on ManyToMany query绕过 Tastypie 忽略多对多查询上的查询集
【发布时间】:2013-04-05 15:26:01
【问题描述】:

我无法让 Tastypie 正确处理多对多查询。

这是我的模型的简化版本。

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 中的建议尝试了“查询集的每个请求更改”,但是当我尝试通过夹克__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)

那么,为什么它被忽略了? 如何强制使用它?

另外,还有其他人知道如何更好地实现这一目标吗?

提前致谢。

杰德

【问题讨论】:

    标签: django-queryset django-orm tastypie


    【解决方案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
    

    您可以随时查看tastepie 的资源代码以了解此功能的工作原理。希望对您有所帮助。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2012-07-11
      • 1970-01-01
      • 2021-11-14
      • 2018-12-01
      • 2019-03-12
      • 1970-01-01
      • 2013-02-01
      • 2018-10-16
      相关资源
      最近更新 更多