mardi 17 janvier 2017

Django Rest Framework Viewsets - Adapter/Service Layer Pattern

I've decided to take the plunge and code a new Django project using the Service Layer / Adapter pattern (Might be known as the Interface pattern in PHP) from the very beginning.

It's actually working pretty well for base Django.

However, I can't wrap my head around how to overcome this hurdle inside Django Rest Framework.

I'll ask the question and then layout the code below.

Question: How do I stay true to separating my data access layer and my business logic (inside the services layer) while using Django Rest Framework's viewsets and satisfying its needs for the queryset attribute to be an instance of 'Queryset'.

Code

  • Contract
  • Services
  • Viewsets

Contract

from exceptions import ServiceLayerFunctionMissing


class ChecksContract:
    @classmethod
    def get_checks(cls):
        """Retrieve all the checks."""
        raise ServiceLayerFunctionMissing('get_checks not implemented')

Services

from checks.contract import ChecksContract
from checks.models import Check


class ChecksServices(ChecksContract):
    @classmethod
    def get_checks(cls):
        return Check.objects.all()

Viewsets

from rest_framework import viewsets

from checks.serializers import CheckSerializer
from checks.services import ChecksServices


class CheckViewSet(viewsets.ModelViewSet):
    queryset = ChecksServices.get_checks()
    serializer_class = CheckSerializer

So, the problem I have is with the line queryset = ChecksService.get_checks().

The construct Queryset is a django.core.db class. It has a very specific API and with that one line I've tightly coupled my viewset to my data access layer. This defeats my purposes of using the Service Layer / Adapter pattern which is to allow a very painless 'swap' of the ORM.

Ideally, I'd have ChecksServices.get_checks() return a list.

Why use this at all? Django Rest Framework handles API routes so beautifully and, to me at least, intuitively. The pagination for example isn't something I care to implement myself, I don't think.

What do you think?

BTW - I know this isn't a truly full proof service layer pattern - I think it lacks sufficient duck typing and true contract implementation. I'll get to that. For now, I lead the project code so I will keep an eye on PRs until I can find a suitable implementation for it.

Aucun commentaire:

Enregistrer un commentaire