Search code examples
djangoapiresourcesnestedtastypie

Nested Resource for many to many relationship in tastypie. Parent Child relationship


I have two resources, customer and Phone (I made it simple here by only including few fields). Different customers can have the same type of phone. I wrote my Modelresource class and access the API through /customer/ and /phone/

Now what I want to do is get the phone for a certain customer. so /customer/1/phone/

These are what my classes look like.

Models.py

# Defines the phone Model

class Phone(models.Model):
    phone_id= models.AutoField(primary_key=True)
    phone_type = models.CharField(max_length=100)


# Defines the Customer Model

class Customer(models.Model):
    customer_id= models.AutoField(primary_key=True)
    phone = models.ManyToManyField(Phone) 

Api.py

class PhoneResource(ModelResource):
    class Meta:
        queryset = Phone.objects.all()
        allowed_methods = ['get']
        resource_name = 'phone'

class CustomerResource(ModelResource):
    phone = fields.ManyToManyField(PhoneResource, "phone")

    class Meta:
        queryset = Customer.objects.all()
        allowed_methods = ['get', 'patch', 'put']
        resource_name = 'customer'
        authentication = Authentication()
        authorization = Authorization()

    def prepend_urls(self):
        return [
            url(r'^(?P<resource_name>%s)/(?P<pk>\w[\w/-]*)/phone%s$' %
                (self._meta.resource_name, trailing_slash()),
                self.wrap_view('get_customer_phone'), name='customer_phone'),
        ]

    def customer_phone(self, request, **kwargs):
        # My Question is what goes in this function 
        # I want to get only the phones for the given customer, and exclude other phones that does not belong to them

I have looked into http://django-tastypie.readthedocs.org/en/latest/cookbook.html#nested-resources

But it doesn't work. I keep getting all the phones back, not just the phone that belongs to a certain customer. So if John had an android and an ios, it should return both list, but if John had android it should only return android. But doing this I am getting all the phone in the Phone model.


Solution

  • Models:

    class Phone(models.Model):
        phone_id= models.AutoField(primary_key=True)
        phone_type = models.CharField(max_length=100)
    
    
    # Defines the Customer Model
    
    class Customer(models.Model):
        customer_id= models.AutoField(primary_key=True)
        phones = models.ManyToManyField(Phone, related_name='customers')
    

    Api:

    class PhoneResource(ModelResource):
        # TODO: update path
        customers = fields.ManyToManyField('path.to.CustomerResource', "customers")
    
        class Meta:
            queryset = Phone.objects.all()
            allowed_methods = ['get']
            resource_name = 'phone'
    
    class CustomerResource(ModelResource):
        phones = fields.ManyToManyField(PhoneResource, "phones")
    
        class Meta:
            queryset = Customer.objects.all()
            allowed_methods = ['get', 'patch', 'put']
            resource_name = 'customer'
            authentication = Authentication()
            authorization = Authorization()
    
        def prepend_urls(self):
            return [
                url(r'^(?P<resource_name>%s)/(?P<pk>\w[\w/-]*)/phone%s$' %
                    (self._meta.resource_name, trailing_slash()),
                    self.wrap_view('get_customer_phone'), name='customer_phone'),
            ]
    
        def get_customer_phone(self, request, **kwargs):
            try:
                bundle = self.build_bundle(data={'pk': kwargs['pk']}, request=request)
                obj = self.cached_obj_get(bundle=bundle, **self.remove_api_resource_names(kwargs))
            except ObjectDoesNotExist:
                return HttpGone()
            except MultipleObjectsReturned:
                return HttpMultipleChoices("More than one resource is found at this URI.")
    
            phone_resource = PhoneResource()
            return phone_resource.get_list(request, customers=obj.pk)