Code generators are a good way to save time. Most of my projects have two main parts:
- The application server written using Django
- The user interface written in Flutter
I create a lot of the structure in Django first. Most of this is designing the tables by writing out their structure using classes in “models.py”. Eventually I get to writing the user interface and I have to create the matching Flutter classes that mirror the tables in Django.
If I only needed to write 3 or 4 classes and if I got the model classes perfect on the first try, I probably wouldn’t bother with a code generator. All projects I’ve worked on use much more than 3 and I have to update the models often. After only a couple of projects, the time I spent writing the code for the code generator is saving me a lot of time. It is a great tool for creating reliable code.
Python’s introspection provides a good way to create the code generator. In my work I use Django Rest Framework and I use the view classes that come with the framework. Each of these class based views are linked to a Serializer class which in turn are, in most cases, linked to a model class. My generator only needs to work at the Serializer level because there is enough information there to generate the Flutter classes.
I wrote a set of functions that loads Django and then iterates over the entries in urls.py and inspects the linked Serializers to create the matching Flutter classes for the models. In addition to that, I have API class that I generate using the urls.py information to retrieve the object from the application server.
There are a couple of steps that I need to follow to make sure that code generation works properly:
- Use class based views and link the serializer to the view class
- I create two API endpoints for each class: (1) The detail endpoint (e.g. /api/state/:id) and the (2) Create/List endpoint (e.g. /api/state/). I make sure that the base URL is the same for both, that way a class and all it’s operations can be handled with a single URL.
- I recommend avoiding the “dynamic” type in Flutter. This is possible by being very strict in how you define your serializers and avoiding certain Django Rest Framework field types.
- I ended up creating my own list of words to help with changing my underscore field names to camel case Flutter field names.
The process of creating the code generator is slow and involves working in the interactive console and playing with the various objects to see where data is and what data is returned in various situations to figure out how to write functions that will properly discern the objects and generate the code I want.
I am working on a series of posts that will look at my work. In the next post I will look at the Django application whose classes I want to mirror in Flutter.