Part 2: Using Python introspection to generate Flutter classes from Django (with rest-framework): The Django Application

In the previous post I introduced the idea of using Python introspection to generate Flutter classes. In this post I will create a sample structure of what I want to create. In this very simple example, I’m creating an app to collect information (numeric) which I want to graph and have some simple analysis performed (max, min, average, etc…).

I’m assuming you know how to create a Django project already. If you don’t, then follow their tutorial!

The Django Appplication

I start with the model file (models.py):

from django.db import models
from django.contrib.auth.models import User
from django.utils import timezone


class Stat(models.Model):
    user = models.ForeignKey(User, on_delete=models.CASCADE)
    type = models.ForeignKey('StatType', on_delete=models.CASCADE)
    value = models.DecimalField(max_digits=19, decimal_places=10)
    created_on = models.DateTimeField(default=timezone.now, editable=False)
    modified_on = models.DateTimeField(default=timezone.now, editable=False)

    def __str__(self):
        return "{}: {} {} ({})".format(self.type.name, self.value, self.type.units, self.user.email)


class StatType(models.Model):
    user = models.ForeignKey(User, on_delete=models.CASCADE)
    name = models.CharField(max_length=100)
    units = models.CharField(max_length=50)
    created_on = models.DateTimeField(default=timezone.now, editable=False)
    modified_on = models.DateTimeField(default=timezone.now, editable=False)

    def __str__(self):
        return "{} ({})".format(self.name, self.user.email)

Two models which will eventually become the database tables. I added the built-in Django auth app so that my app can be multi-user. I also created the “__str__” functions so that when I used Django Admin, it will be easier to identify specific rows of data.

This leads to a very simple set of Serializers (serializers.py):

from rest_framework import serializers
from .models import *


class StatSerializer(serializers.ModelSerializer):
    class Meta:
        model = Stat
        fields = '__all__'


class StatTypeSerializer(serializers.ModelSerializer):
    class Meta:
        model = StatType
        fields = '__all__'


class UserSerializer(serializers.ModelSerializer):
    class Meta:
        model = User
        fields = '__all__'

And the matching Views (views.py) will look like:

from .serializers import *
from rest_framework import generics
from rest_framework.permissions import IsAdminUser, BasePermission, AllowAny, IsAuthenticated
# Create your views here.


class StatList(generics.ListCreateAPIView):
    queryset = Stat.objects.all()
    serializer_class = StatSerializer
    permission_classes = [IsAuthenticated]


class StatDetail(generics.RetrieveUpdateDestroyAPIView):
    queryset = Stat.objects.all()
    serializer_class = StatSerializer
    permission_classes = [IsAuthenticated]


class StatTypeList(generics.ListCreateAPIView):
    queryset = StatType.objects.all()
    serializer_class = StatTypeSerializer
    permission_classes = [IsAuthenticated]


class StatTypeDetail(generics.RetrieveUpdateDestroyAPIView):
    queryset = StatType.objects.all()
    serializer_class = StatTypeSerializer
    permission_classes = [IsAuthenticated]

And then we create the Urls (urls.py) file. I think that it is recommended that you create a urls.py for the specific app, but in this case, since I’m keeping it simple, I’m going to show you the project’s urls.py:

from django.contrib import admin
from django.urls import path
from statsapp import views as stat_views

urlpatterns = [
    path('admin/', admin.site.urls),
    path('api/s/stat/', stat_views.StatList.as_view()),
    path('api/s/stat/<int:pk>/', stat_views.StatDetail.as_view()),
    path('api/s/stattype/', stat_views.StatTypeList.as_view()),
    path('api/s/stattype/<int:pk>/', stat_views.StatTypeDetail.as_view()),
]

Finally a Django Admin (admin.py) file to easily add and edit records:

from django.contrib import admin
from .models import *
# Register your models here.


class StatAdmin(admin.ModelAdmin):
    list_display = ('id', 'user', 'type', 'value', 'created_on')
    readonly_fields = ('created_on', 'modified_on',)


admin.site.register(Stat, StatAdmin)


class StatTypeAdmin(admin.ModelAdmin):
    list_display = ('id', 'user', 'name', 'units', 'created_on')
    readonly_fields = ('created_on', 'modified_on',)


admin.site.register(StatType, StatTypeAdmin)

The code above is working code. I created a Django project called “statsproj” and then I created the Django app called “statsapp”. I put it all inside a set of docker containers and run it using docker-compose. I’ve done all this to make sure that the code I write in this simple example is working.

The models are very simple and we wouldn’t need a code generator to save time to create the Flutter classes, but I will demonstrate how easy it is to make changes to the Django models and then have these changes reflected in the Flutter classes. In addition to this, there are ways to enhance the Flutter classes such that regenerating the classes from Django doesn’t undo the enhancements on the Flutter side.

In the next post, I’ll describe the Flutter classes that I want to create.

Similar Posts