1

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?

2 Answers 2

1

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.

Sign up to request clarification or add additional context in comments.

2 Comments

works ! thank you. but how can i get the filename only? with req.buuild_absolute_uri i gett the full api uri. i just need the filename
You're welcome. For returning name you just have to replace the line req.build_absolute_uri(obj.country.image.url) with obj.country.image.name in your serializer.
0
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,
            })


Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.