mardi 30 juillet 2019

Most Pythonic/Django way to dynamically load client libraries at runtime

I'm writing a Django application in which we will have multiple client libraries that make calls to third party APIs. We want to be able to determine which client library to load at runtime when calling different endpoints. I'm trying to determine the most Django/Pythonic way to do this

The current idea is to store class name in a model field, query the model in the View, and pass the class name to a service factory that instantiates the relevant service and makes the query. I've also considered writing a model method that uses reflection to query the class name

For example lets say we have a model called Exchange that has an id, a name, and stores the client name.

class Exchange(models.Model):
    exchange_name = models.CharField(max_length=255)
    client_name = models.CharField(max_length=255)

    def __str__(self):
        return self.exchange_name

Then in the View we might have something like:

from rest_framework.views import APIView
from MyProject.trades.models import Exchange
from django.http import Http404
from MyProject.services import *


class GetLatestPrice(APIView):

    def get_object(self, pk):
        try:
            exchange = Exchange.objects.get(pk=pk)
        except Exchange.DoesNotExist:
            raise Http404

    def get(self, request, pk, format=None):
        exchange = self.get_objectt(pk)
        service = service_factory.get_service(exchange.client_name)
        latest_price = service.get_latest_price()
        serializer = PriceSerializer(latest_price)
        return Response(serializer.data)

This syntax may not be perfect but it hasn't been tested. But the idea is that maybe we have

ExchangeA - client1 
ExchangeB - client2
ExchangeC - client3

And for each client we have a service class that all inherit from the same Abstract Base. Each service has an override that are all the same. That way when you call /api/get_latest_price you pass the Exchange id as a query param and the code loads whatever service and client library is relevant. This would be so we could easily add new types to the system, have consistent and small Views, and decouple the business logic. Is this an acceptable, scalable pythonic method? Or is there a better solution for it? Essentially the problem is implementing Polymorphism in django and seperating the domain model from the data model. This has to be a solved problem so I'm curious on the way other people might be doing this. I know it's unusual to be calling a third party API like this but since we are forced to I want to do it in the cleanest most scalable way possible.

Aucun commentaire:

Enregistrer un commentaire