Purpamine
Purpamine

Reputation: 141

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.

Upvotes: 2

Views: 508

Answers (2)

Se&#225;n Hayes
Se&#225;n Hayes

Reputation: 4360

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)

Upvotes: 1

svfat
svfat

Reputation: 3363

Are you sure that you need separate prepend_urls for that? You can get phone lists for each customer buy adding full=True to ManyToManyField arguments:

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

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

Upvotes: 0

Related Questions