martin
martin

Reputation: 155

Django Rest Framework: Custom Views

i have a django installation with currently two apps ( common / destinations ) and i want to create custom api views across these apps.

in common i have a model country

models.py app common

from django.db import models

# Create your models here.

class Country(models.Model):
    CONTINENTS = (
        ('Europe', 'Europe'),
        ('Asia', 'Asia'),
        ('Africa', 'Africa'),
        ('northamerica', 'North America'),
        ('southamerica', 'South America'),
        ('australia', 'Australia')
    )
    name = models.CharField(max_length=120)
    code = models.CharField(max_length=2)
    continent = models.CharField(max_length=11, choices=CONTINENTS)
    content = models.TextField()
    image = models.FileField()

models.py app destination

from django.db import models

# Create your models here.

class Destination(models.Model):
    name = models.CharField(max_length=120)
    code = models.CharField(max_length=3)
    country = models.ForeignKey("common.Country", on_delete=models.CASCADE)
    image = models.FileField()

serializers.py app destination

from rest_framework import serializers
from common.serializers import CountrySerializer
from .models import Destination 

class DestinationSerializer(serializers.ModelSerializer):

country = CountrySerializer()

class Meta:
    model = Destination
    fields = ("id", "name", "code", "country", "image")

views.py app destination

from rest_framework import views
from rest_framework.response import Response
from .serializers import DestinationSerializer, ImageSerializer
from .models import Destination

# Create your views here.

class DestinationView(views.APIView):
    def get(self, request, code):
        destination =  Destination.objects.filter(code=code.upper())
        if destination:
            serializer = DestinationSerializer(destination, many=True)
            return Response(status=200, data=serializer.data)
        return Response(status=400, data={"Destination not found"})

When i make a API call /api/destination/PMI everything works. i get my destination from destination app and country from common app.

**GET /api/destination/**

HTTP 200 OK
Allow: GET, HEAD, OPTIONS
Content-Type: application/json
Vary: Accept

[
    {
        "id": 1,
        "name": "Palma de Mallorca",
        "code": "PMI",
        "country": {
            "id": 1,
            "name": "Spain",
            "code": "ES",
            "continent": "Europe",
            "content": "Lorem Ipsum",
            "image": "http://localhost:1000/media/logo.svg"
        },
        "image": "http://localhost:1000/media/2020-08-03_07-40.png"
    }
]

Now i want to create a view which only returns the images from common / destination

e.g.

GET **/api/destination/pmi/image**
HTTP 200 OK
Allow: GET, HEAD, OPTIONS
Content-Type: application/json
Vary: Accept
[
    {
         "code": "pmi",
         "destination_image" : "image.png",
         "country_image" : "country.png" 
    }
]

how, if possible, can i achieve that?

Upvotes: 1

Views: 4980

Answers (2)

Roham
Roham

Reputation: 2110

One easy and clean way to do that is to have an extra serializer for your view like:

class ExtraSerializer(serializers.ModelSerializer):
    destination_image = serializers.SerializerMethodField()
    country_image = serializers.SerializerMethodField()

    class Meta:
        model = Destination
        fields = (
            'code', 'destination_image', 'country_image'
        )

    def get_destination_image(self, obj):
        req = self.context['request']
        # build_absolute_uri will convert your related url to absolute url
        return req.build_absolute_uri(obj.image.url)

    def get_country_image(self, obj):
        req = self.context['request']
        return req.build_absolute_uri(obj.country.image.url)

Also note that you should pass the request from your view to context of your serializer to build an absolute url (Example: ExtraSerializer(queryset, many=True, context={'request': self.request}) or context={'request': request} if you're using same APIView as before) and then use the data of this serializer.

Upvotes: 1

satyajit
satyajit

Reputation: 694

class All_HomePage(APIView):

    def get(self,request):

        #get destination_data
        data = Destination.objects.all()
        destination_ser = DestinationSerializer(data,many=True)
        destination_data=[]
        for record in destination_ser.data:
            code = record['code']
            image = record['image']
            destination_data.append({"code":code ,"destination_image":image})


        #get country_data
        data = Country.objects.all()
        country_ser = CountrySerializer(data,many=True)
        country_data=[]
        for record in country_ser.data:
            image = record['image']
            country_data.append({"country_image":image,})


        return Response({
            "destination_data":destination_data, "country_data":country_data,
            })


Upvotes: 0

Related Questions