Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Combine Related Resources With TastyPie

How can I combine multiple Resources in TastyPie? I have 3 models I'd like to combine: users, profiles and posts.

Ideally I'd like profiles nested within user. I'd like to expose both the user and all of the profile location from UserPostResource. I'm not sure where to go from here.

class UserResource(ModelResource):

    class Meta:
        queryset = User.objects.all()
        resource_name = 'user'
        fields = ['username','id','date_joined']

        #Improper Auth
        authorization = Authorization()

class UserProfileResource(ModelResource):

    class Meta:
        queryset = UserProfile.objects.all()
        resource_name = 'profile'


class UserPostResource(ModelResource):
    user = fields.ForeignKey(UserResource,'user', full=True)


    class Meta:
        queryset = UserPost.objects.all()
        resource_name = 'userpost'

        #Improper Auth
        authorization = Authorization()

Here are my models:

class UserProfile(models.Model):

    user = models.OneToOneField(User)

    website = models.CharField(max_length=50)
    description = models.CharField(max_length=255)
    full_name = models.CharField(max_length=50)


class UserPost(models.Model):
    user = models.ForeignKey(User)

    datetime = models.DateTimeField(auto_now_add=True)
    text = models.CharField(max_length=255, blank=True)
    location =  models.CharField(max_length=255, blank= True)
like image 612
aroooo Avatar asked Sep 15 '12 09:09

aroooo


1 Answers

Tastypie fields (when the resource is a ModelResource) allow passing in the attribute kwarg, which in turn accepts regular django nested lookup syntax.

So, first of all this might be useful:

# in UserProfile model (adding related_name)
user = models.OneToOneField(User, related_name="profile")

and given the above change, the following:

from tastypie import fields

class UserResource(ModelResource):
    # ... 
    website = fields.CharField(attribute = 'profile__website' )
    description = fields.CharField(attribute = 'profile__description' )
    full_name = fields.CharField(attribute = 'profile__full_name' )
    # ...

will expose the data from UserProfile model within the UserResource.

Now if you'd like to expose a list of locations (coming from UserPost) within the UserResource you will have to override one of Tastypie methods. According to the documentation a good candidate would be the dehydrate() method.

Something like this should work:

# in UserPost model (adding related_name)
user = models.ForeignKey(User, related_name="posts")

class UserResource(ModelResource):
    # ....
    def dehydrate(self, bundle):
        posts = bundle.obj.posts.all()
        bundle.data['locations'] = [post.location for post in posts]
        return bundle
    # ...
like image 109
kgr Avatar answered Nov 16 '22 07:11

kgr