Search code examples
pythondjangoapireactjstastypie

Fetch Foreign key object from an api using reactjs


I am so confused and it is becoming very difficult for me to carry on my project. I am developing rental system application where user can register their space(includes ownername,listingname,email,summary,multiple images of their room and etc).I have created two table for this. One for rental details and another gallery for multiple images for one rent. I created an api resource for both. I could save data to my database also.I succeed in fetching rental details using reactjs and tastpyie but i could not fetch image associated with that rental.What should i do for this?

Models.py

class Rental(models.Model):
    ownerName = models.CharField(_("Owner's Name"),max_length=255, blank=True,null=True,
        help_text=_("Owner's Full Name"))
    listingName =  models.CharField(_("Lisitng Name"), max_length=255, blank=False,null=True,
        help_text=_("Title of the rental space"))
    summary = models.TextField(max_length=500, blank=True,null=True,help_text=_("Description of the rental space"))
    room = models.PositiveIntegerField(_("No of Rooms"), blank=False, null=True,
        help_text=_("Number of bedrooms available"))
    price = models.PositiveIntegerField(blank=False,null=True,
        help_text=_("Rental price of the space per month"))

    def save_images(self, images,instance):
        for image in images:
            GalleryImage.objects.create(image=image, rental=instance)


    def __str__(self):
        return self.listingName


class GalleryImage(models.Model):
    rental = models.ForeignKey('Rental',on_delete=models.CASCADE,blank=True,null=True,
                                verbose_name=_('Rental'), related_name="gallery")
    image = models.FileField(blank=True,upload_to='upload/',null=True)

api.py

class MultipartResource(object):
    def deserialize(self, request, data, format=None):
        if not format:
            format = request.META.get('CONTENT_TYPE', 'application/json')
        if format == 'application/x-www-form-urlencoded':
            return request.POST
        if format.startswith('multipart'):
            data = request.POST.copy()
            data.update(request.FILES)
            return data
        return super(MultipartResource, self).deserialize(request, data, format)

    def put_detail(self, request, **kwargs):
        if request.META.get('CONTENT_TYPE').startswith('multipart') and \
                not hasattr(request, '_body'):
            request._body = ''
        return super(MultipartResource,self).put_detail(request,**kwargs)

    def patch_detail(self, request, **kwargs):
        if request.META.get('CONTENT_TYPE', '').startswith('multipart/form-data') and not hasattr(request, '_body'):
             request._body = ''
        return super(MultipartResource, self).patch_detail(request, **kwargs)

class RentalResource(MultipartResource,ModelResource):
    class Meta:
        queryset = Rental.objects.all()
        resource_name = 'rental'
        allowed_methods = ['get', 'post','put']
        fields = ['listingName','ownerName','room','price','summary']
        filtering = { "property" : ALL , "room":ALL,"price":ALL}
        authorization = DjangoAuthorization()

class GalleryImageResource(ModelResource):
    rental = fields.ForeignKey(RentalResource, 'rental')
    class Meta:
        queryset = GalleryImage.objects.all()
        resource_name = 'gallery'
        allowed_methods = ['get','post','put']
        authorization = DjangoAuthorization()

reactjs code for fetching data

export default class RoomList extends React.Component{
    constructor(props){
        super(props);
        this.state = { rooms: [] }
    }

    componentDidMount(){
        console.log('componentDidMount');
        this.loadRoomFromServer();
    }

    loadRoomFromServer(){
        $.ajax({
            url:'/api/v1/rental/',
            dataType:'json',
            success: (data) => {
                console.log('data',data);
                this.setState({rooms: data.objects});
                console.log('success');
              },
              error: (xhr, status, err) => {
                console.error(url, status, err.toString());
              }
            });
    }

    render(){
        console.log('rooms',this.state.rooms);
        let listOfRoom = this.state.rooms.map((room,id)=>{
            return(
                    <Rooms key={id} name={room.listingName} price={room.price} number={room.room} />
                )
        });
        console.log('listOfRoom',listOfRoom);
        return(
                <div className="container-fluid">
                    <div className="row">
                            { listOfRoom }
                    </div>
                </div>
            )
    }
}

class Rooms extends React.Component{
    render(){
        return(
                <div className="col-md-4">
                    <h2>{this.props.name}</h2>
                    <p>{this.props.price}</p>
                    <p>{this.props.number}</p>
                </div>
            )
    }
}

as the url will be different for rental and gallery how could i now fetch images associated with that rent? Your help will be appreciated. Thanks


Solution

  • See: https://django-tastypie.readthedocs.org/en/latest/resources.html?highlight=relationships#reverse-relationships

    Tastypie doesnt automatically add relationship fields, you need to do them manually.

    If you want to hit the rental endpoint and get related gallery resources, do the following:

    class RentalResource(MultipartResource,ModelResource):
        gallery = fields.ToMany('path.to.GalleryImageResource', 'gallery', related_name='rental', full=True)
    
        class Meta:
            queryset = Rental.objects.all()
            resource_name = 'rental'
            allowed_methods = ['get', 'post','put']
            fields = ['listingName','ownerName','room','price','summary']
            filtering = { "property" : ALL , "room":ALL,"price":ALL}
            authorization = DjangoAuthorization()
    
    class GalleryImageResource(ModelResource):
        rental = fields.ForeignKey(RentalResource, 'rental', full=False, null=True, blank=True)
    
        class Meta:
            queryset = GalleryImage.objects.all()
            resource_name = 'gallery'
            allowed_methods = ['get','post','put']
            authorization = DjangoAuthorization()