Tastypie ManyToMany过滤器

时间:2013-12-31 01:49:01

标签: django tastypie

我无法将过滤器应用于与tastypie的ManyToMany关系。这是我的模特

class Post(models.Model):
    user = models.ForeignKey(User, related_name='posts')
    title = models.TextField()

    class Meta:
        """ Meta """
        db_table = "post"

class Category(models.Model):
    posts = models.ManyToManyField(Post, through='PostCategory', null = True, blank = True)
    name = models.TextField()

    class Meta:
        """ Meta """
        db_table = "category"

class PostCategory(models.Model):
    post = models.ForeignKey(Post, related_name='posts')
    category = models.ForeignKey(Category, related_name='categories')

    class Meta:
        """ Meta """
        db_table = "post_category"

这是api.py

class CategoryResource(ModelResource):
    class Meta:
        queryset = Category.objects.all()
        resource_name = 'category'
        filtering = {
            'id': ['exact'],
        }

class PostCategoryResource(ModelResource):
    category = fields.ToOneField(CategoryResource, 'category', full=True)
    class Meta:
        queryset = PostCategory.objects.all()
        resource_name = 'postcategory'
        filtering = {
            'category': ALL_WITH_RELATIONS,
            'id': ['exact'],
        }

class PostResource(ModelResource):
    user = fields.ToOneField(ProfileResource, 'user', full=True)
    categories = fields.ToManyField(PostCategoryResource,
            attribute=lambda bundle: bundle.obj.categories.through.objects.filter(
                post=bundle.obj,)
            or bundle.obj.categories, full=True)

    class Meta:
        queryset = Post.objects.all()
        resource_name = 'post'
        filtering = {
            'user': ALL_WITH_RELATIONS,
            'categories': ALL_WITH_RELATIONS,
            'id': ['exact'],
        }


我的目标是能够通过user_id或category_id获取所有帖子。以下工作正如我所希望的那样:
http://127.0.0.1/api/v1/post/?format=json&user__id=2

但是,我没有得到像这样的工作:
http://127.0.0.1/api/v1/post/?format=json&categories__category__id=3

这是我得到的错误:

  

{" error_message":"序列项0:预期字符串,找到函数","追溯":"追溯>(最近一次调用last):\ n \ n File \" /usr/lib/python2.6/site-packages/django_tastypie-0.11.0-> py2.6.egg / tastypie / resources.py \" ,第195行,在wrapper \ n response = callback(request,> * args,** kwargs)\ n \ n File \" /usr/lib/python2.6/site-packages/django_tastypie-0.11。 0-> py2.6.egg / tastypie / resources.py \",第426行,在dispatch_list \ n中返回> self.dispatch(' list',request,** kwargs) \ n \ n文件\" /usr/lib/python2.6/site-> packages / django_tastypie-0.11.0-py2.6.egg / tastypie / resources.py \",第458行,在dispatch \ n> response = method(request,** kwargs)\ n \ n File \" /usr/lib/python2.6/site-> packages / django_tastypie-0.11.0-py2。 6.egg / tastypie / resources.py \",第1266行,在get_list \ n> objects = self.obj_get_list(bundle = base_bundle,** self.remove_api_resource_names(kwargs))\ n \ n>文件\" / usr / lib中/python2.6/site-packages/django_tastypie-0.11.0->py2.6.egg/tastypie/resources.py\" ;,第2044行,在obj_get_list \ n applicable_filters => self.build_filters(过滤器=过滤器)\ n \ n文件\" /usr/lib/python2.6/site-> packages / django_tastypie-0.11.0-py2.6.egg / tastypie / resources.py \" ,第1949行,在> build_filters \ n db_field_name = LOOKUP_SEP.join(lookup_bits)\ n \ nTypeError:序列项> 0:预期字符串,找到函数\ n"}

3 个答案:

答案 0 :(得分:1)

当field属性由lambda表示时,看起来像Tasty一样不允许你按虚拟字段过滤。

您可以对其进行一些修改:

class PostCategory(models.Model):
    post = models.ForeignKey(Post, related_name='categories')
    category = models.ForeignKey(Category)


class PostResource(ModelResource):
    user = fields.ToOneField(ProfileResource, 'user', full=True)
    categories = fields.ToManyField(PostCategoryResource, 'categories', full=True)

    class Meta:
        queryset = Post.objects.all()
        resource_name = 'post'
        filtering = {
            # filter by user
            'user': ALL_WITH_RELATIONS,

            #filter by category id
            'categories': ALL_WITH_RELATIONS,
            'category': ALL,
            'id': ['exact'],
        }

答案 1 :(得分:0)

(global-set-key (kbd "<C-wheel-up>") 'text-scale-increase)
(global-set-key (kbd "<C-wheel-down>") 'text-scale-decrease)

答案 2 :(得分:0)

今天,当我收到一个好吃的错误,试图过滤可调用attribite的字段时,我偶然发现了这个线程:TypeError: sequence item 1: expected string or Unicode, function found

看来,好吃的东西要求attribute是一个字符串才能被它过滤,但是当您想过滤嵌套对象时可以调用。为了解决这个问题,我实现了一个CallableString,它是一个可以调用的字符串:

class CallableString(unicode):
    def __init__(self, *args, **kwargs):
        super(CallableString, self).__init__(*args, **kwargs)

    def __call__(self, bundle):
        return InstitutionGroup.objects.published().filter(institutions=bundle.obj)

用您自己的自定义逻辑替换__call__的实现,并将其添加到您的资源字段中:

groups = fields.ToManyField(
    InstitutionGroupResource,
    attribute=CallableString('institution_groups'),
    null=True,
    full=True,
)

我会说这是一个非常棘手的解决方案,可能会有一些副作用,但是现在看来对我来说是有效的-tastypie版本0.13.3