Reputation: 847
I have a slightly complex model structure in django that includes a UserProfile
class UserProfile(models.Model):
shoppinglist = models.ManyToManyField(Offer)
user = models.OneToOneField(User)
follows = models.ManyToManyField('self', related_name='followers', symmetrical=False, blank=True)
and an offer
class Offer(models.Model):
description = models.CharField(max_length=200)
What this means is that each user can follow other users and can create a shopping list with offers they like.
I can create a query to see if an offer is in the shopping list of any of the people I follow like this
profile.follows.filter(shoppinglist=offer)
and it returns a queryset of UserProfile objects.
Now, I have and OfferResource and a UserProfileResource in my tastypie API representing this two models.
What I need to do is, whenever I get a list of Offers, add a custom field to each Offer with the list of people I follow that 'like' that offer.
offer: {
description: 'Something'
liked_by: [
{ ... },
{ ... }
]
}
I know I can override the 'dehydrate' method to add custom fields but if I add
def dehydrate(self, bundle):
bundle.data['liked_by'] = profile.follows.filter(shoppinglist=bundle.obj)
The resulting list of users in the liked_by field is not serialised or dehydrated.
Any Ideas?
Upvotes: 1
Views: 693
Reputation: 491
You can "embed" a bundle by using a lambda function for the "attribute" argument of a ToManyField on your OfferResource. For example:
liked_by = fields.ToManyField(
UserProfileResource,
attribute=lambda bundle: bundle.request.user.get_profile().follows.filter(
shoppinglist=bundle.obj),
full=True,
null=True)
A little bit of documentation on that.
Upvotes: 5
Reputation: 9190
You can use the UserProfileResource to dehydrate a list of objects:
class OfferResource(ModelResource):
...
users = fields.ToManyField(UserProfileResource, attribute='users', full=True)
...
def dehydrate_users(self, bundle):
res = UserProfileResource()
objects = profile.follows.filter(shoppinglist=bundle.obj)
bundles = [res.build_bundle(obj=obj, request=bundle.request) for obj in objects]
return [res.full_dehydrate(bundle) for bundle in bundles]
It's also possible to provide a callable for the attribute
kwarg, but it isn't clear what all you need to be able to look up your profile
object. If you can get it within that scope, then you just need to return a queryset:
class OfferResource(ModelResource):
...
users = fields.ToManyField(UserProfileResource,
attribute=lambda bundle: get_profile(bundle.request).follows.filter(shoppinglist=bundle.obj),
full=True)
Upvotes: 2
Reputation: 3871
To me, it seems like you will probably need to read tastypie docs and figure out what it is that you need to extend. Because my guess is that you will need to extend something there. Not in the model, but in tastypie (serializers, fields). IT is hard to answer because your intent is still not 100% clear.
Also, since you seem to want to aggregate more models, check out if this link helps you:
Upvotes: 0