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