[Django]-How might I join two unrelated Django models via distance?

0πŸ‘

I would recommend using GraphQL/DataLoaders to solve this N+1 problem as DRF is not well suited for it. However, this can be done in DRF by using a custom ListSerializer (django creates one for you behind the scenes automatically) and overloading the to_representation functions of both List/Child serializers:

class SchoolListSerializer(serializers.ListSerializer):
    def to_representation(self, data):
        iterable = data.all() if isinstance(data, models.Manager) else data
        keys = [(item.id, item.location) for item in iterable]
        # perform your bulk nearby query here using the id/locations
        # the result should be a dict with school id keys and list of serialized hospital values
        # {1: [hospital.to_dict(), hospital.to_dict(), ...], ...}
        nearby_by_id = ...
        extra = {
            'nearby_hospitals_by_id': nearby_by_id
        }
        return [
            self.child.to_representation(item, **extra) for item in iterable
        ]

class SchoolSerializer(serializers.ModelSerializer):

    class Meta:
        model = School
        fields = ('location', )
        list_serializer_class = SchoolListSerializer

    def to_representation(self, instance, **extra):
        response = super().to_representation(instance)
        response['nearby_hospitals'] = extra['nearby_hospitals_by_id'][instance.id]
        return response

I left out the actual DB query, however the example will work with any queries regardless of where the data resides.

πŸ‘€Bemis

-1πŸ‘

I’m not sure it’s better, but I think you are taking the problem in the reverse direction. I see no reason for any JOIN at all.

class SchoolSerializer(serializers.ModelSerializer):

    nearby_hospitals = serializers.SerializerMethodField('get_nearby_hospitals')

    class Meta:
        model = School
        fields = ('location', 'nearby_hospitals',)

    def get_nearby_hospitals(self, obj):

        geom = obj.location

        try:
            # why do you query School model if you want nearby hospitals?
            locations = Hospital.objects.filter(location__distance_lte=(geom ,10000))
            return locations # not sure it's the good type to return though
        except:
            return

Leave a comment