| published by | Software Crafts |
|---|---|
| in blog | Software Crafts |
| original entry | Django & REST & APIs |
While lamenting that I'm not in Spain for Django on the Med (but do have other events to go to), I have been reading the recent forum thread about Django & REST and it has provoked some thoughts, some of which I shared directly in the thread, but I hope to expand on them here and likely in another post as I'm not quite done prototyping my ideas.
First there is some obvious core work that needs to be done:
Once we have those in place we are a starting point to focus the main components that make up an API in Django. Primarily it's as follows:
Most of the focus has mostly been on the serialization component, in terms of which option to pick to include or not include, what options are available (or which there are many). However it strikes me that we could take a similar approach to that of the Tasks interface added in 6.0. We need be focusing on the Django API/Protocol for these serialization options to hook into regardless of which option you prefer for a project. This would also allow us to more easily keep up with the latest libraries as they progress in that area.
So what would be required for this API for APIs? I would propose the following:
Based on the above I have been playing around with subclassing neopolitan's CRUDView and had a peek at Emma's djrest2 and have a class that looks like this for now:
class APIView(CRUDView):
def get_serializer_data(self, serializer):
raise NotImplemented
def serialize_many(self, qst):
return [self.serialize_one(obj) for obj in qst]
def serialize_one(self, obj):
serializer = self.serializer_class(obj)
serialized_data = self.get_serializer_data(serializer)
return serialized_data
def serialize(self, context):
data = {}
if self.role == Role.LIST:
data = self.serialize_many(context["object_list"])
if self.role == Role.DETAIL:
data = self.serialize_one(context["object"])
return data
def render_to_response(self, context):
return JsonResponse(
content_type="application/json",
data=self.serialize(context),
)
@classproperty
def url_base(cls):
return f"api/{cls.model._meta.model_name}"
This could then be used as follows:
class ProjectAPIView(APIView):
model = Project
fields = [
"name",
"description",
"created_at",
"updated_at",
"created_by",
]
serializer_class = ProjectSerializer
urlpatterns = ProjectAPIView.get_urls()
There are some very obvious holes in this current code, like the fact that I haven't dealt with creations, updates & deletions. My focus is creating a reasonable API at the view layer which various serialization options could plug into. There is also covering my 3rd point of ORM integration for the options that need it.
I hope this in part keeps the conversation going and we can get some progress made in this area!