Python 🐍 Backends with Django

By Lars Haferkamp on May 1, 2023
Project Python Django

In this post, I’d like to give a quick overview of Django-based backends and their features, and share my very positive experiences from several projects.

Django calls itself

The web framework for perfectionists with deadlines.

What’s in it

Django on Python is like Spring on Java. I really like the all-in-one solution. You just define a data model and get an object-relational mapper and a de-/serializer for API calls out-of-the box. It provides a very convenient versioning of your database schema, but you can still write custom DB migration scripts. You get a template language and form classes if you want to server HTML (I haven’t used it yet). And Django comes with a full-featured and secure authentication system. Oh… and you automatically get an admin interface which you can use to browse and edit the content of your application.

Django REST framwork

For implementing a REST API with Django the Django REST framework (DRF) is your solution. Defining standard REST API operations is super convenient. Mainly you define which Serializer should convert between request/response objects (e.g. in JSON format) and your model. For operations that query data you can simply use the standard Django DB query API to get a queryset. As Serializer you can use a ModelSerializer, which is also very easy to define. Additionally you can define permission classes, that check if the user is allowed to call a certain API operation and filter backends that additionally filter the initial queryset.

Below is a simple example of a Serializer and API operation to get a list of objects. Of course you can also define custom APIs.

class MyDataSerializer(serializers.ModelSerializer):
    class Meta:
        model = MyData
        exclude = ('id',)

class ListMyDataView(ListAPIView):
    schema = AutoSchema(operation_id_base="MyData")
    serializer_class = MyDataSerializer
    queryset = MyData.objects.all()
    permission_classes = [MyCustomerAccessPermission]
    filter_backends = [MyDataIsAvailableFilter, Top10Filter]

If you use these APIView and Serializer classes of DRF you can generate an OpenAPI schema by running the Django command:

./manage.py generateschema --file openapi-schema.yml

Django commands

Django also offers a way to run specific code from the command line called django-admin commands. This is useful for scheduling certain jobs or defining steps in a data-processing pipeline.

I managed to combine Azure Functions and Django commands for scheduled jobs, which I described on Stackoverflow. The central part to get a Django command running inside an Azure function code is in the following lines (would work probably similar for AWS Lambda):

os.environ.setdefault('DJANGO_SETTINGS_MODULE', 'mydjango.settings')
django.setup()
call_command('my_command') 

I also set up the Azure function which needs to run as custom Linux image via Terraform which was quite cumbersome 😰

Django DB schema versioning and migration

Django offers commands which allows you to convert your Python data model changes into DB schema changes.

After you added a new data model class or only added attributes, you just need to run

./manage.py makemigrations

which generates a Python script to migrate the DB schema accordingly. This Python script automagically get’s some sort of a version number e.g. 0019_alter_mydata_title.py followed by a short description of the changes. The version number is just a helper, in fact inside each migration script you define one (or more) dependencies, these are predecessors i.e. migrations that must have been successful before the current migration is executed. A (generated) migration contains just a class with the dependencies and operations.

class Migration(migrations.Migration):
    dependencies = [('mymodule', '0018_myotherdata_attribute1'),]
    operations = [
        migrations.AlterField(
            model_name='mydata',
            name='title',
            field=models.CharField(max_length=128),
        ),
    ]

Operations can be changes to the DB scheme or also plain SQL statements.

By running

./manage.py migrate

the last migration is performed on the connected DB. In fact if you set up a new DB or are some migrations behind Django will automatically detect it and perform any missing migrations. You can also write a custom migration script e.g. if you need to convert some data in between and add it to the migration tree.

Summary

This has only been a quick introduction to the main features of Python backends with Django, but I hope it’s already helped you understand the benefits. I can really recommend using it for smaller projects, and there is a large community behind it if you get into trouble.

For a follow-up and links to the official documentation, see the Getting started with Django guide.

Attribution

The header image is licensed by 1840151sudarshan under Creative Commons Attribution-Share Alike 4.0 International, CC BY-SA 4.0 via Wikimedia Commons

Contact me via LinkedIn:Linkedin icon
© Copyright 2023 by Lars Haferkamp - Freelancer. Built with ♥ by CreativeDesignsGuru.

Impressum