Tastypie, filtering many to many relationships
Asked Answered
D

2

6

I have two models that are linked by another model through a many to many relationship.

Here's the models themselves

class Posts(models.Model):
    id = models.CharField(max_length=108, primary_key=True)
    tags = models.ManyToManyField('Tags', through='PostTags')


class Tags(models.Model):
    id = models.CharField(max_length=108, primary_key=True)
    posts = models.ManyToManyField('Posts', through='PostTags')

class PostTags(models.Model):
    id = models.CharField(max_length=108, primary_key=True)
    deleted = models.IntegerField()
    post_id = models.ForeignKey('Posts', db_column='post_field')
    tag_id = models.ForeignKey('Tags', db_column='tag_field')

And the tastypie resources

class PostsResource(ModelResource):
    tags = fields.ToManyField('django_app.api.TagsResource', 'tags', null=True)
    class Meta:
        queryset = Posts.objects.filter(deleted=0)
        resource_name = 'posts'

class TagsResource(ModelResource):
    posts = fields.ToManyField('django_app.api.PostsResource', 'posts', null=True)
    class Meta:
        queryset = Tags.objects.filter(deleted=0)
        resource_name = 'tags'

On the posttags table there is a deleted flag, is it possible to only return linked results when the deleted flag in PostTags is 0?

I have tried this filter attribute in tastypie but it only seems to care about the flag in the linked table(ie tags or posts) not the actual table doing the linking.

Dominicadominical answered 19/7, 2012 at 9:27 Comment(2)
Have you tried queryset = Posts.objects.filter(posttags__deleted=0) in Meta for each Resource?Indira
It's odd, that half works. As in if I print the queryset.query, it's doing the correct SQL statement(as in it's got where deleted=0). But the results returned via the api request still seems to ignore the flag.Dominicadominical
P
8

You can filter fields using lambda bundle attribute showing table name and field name.

tags = fields.ToManyField('django_app.api.TagsResource', attribute=lambda bundle: bundle.obj.tags.filter(tags__deleted=0))
Predestinarian answered 23/7, 2012 at 10:4 Comment(0)
C
1

Wow... I've been looking all day for this! the "attribute" is exactly what I was looking for. I almost started hacking at my models to do the filtering there out of despair.

From the Resource Field documentation for ToManyField:

Provides access to related data via a join table.

This subclass requires Django’s ORM layer to work properly.

This field also has special behavior when dealing with attribute in that it can take a callable. For instance, if you need to filter the reverse relation, you can do something like:

subjects = fields.ToManyField(SubjectResource, attribute=lambda bundle: Subject.objects.filter(notes=bundle.obj, name__startswith='Personal'))
Colecolectomy answered 17/8, 2014 at 23:7 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.