Article
· Jul 30, 2022 5m read

Introduction to Django part 3

Continuing to  observe the possibilities of Django, and usage with IRIS. The first we have looked how to define models and connect to tables already existing in IRIS, than we extended embedded Django Administration portal, with an ability to see what data we have in that models, with filters, editing and even pagination.

Time to go to real action, now we a going to create some REST API, on Django, based on the same data, we used before from the package posts-and-tags.

To do so, we will use Django REST Framework

Django REST Framework

Django REST framework is a powerful and flexible toolkit for building Web APIs.

Some reasons you might want to use REST framework:

  • The Web browsable API is a huge usability win for your developers.
  • Authentication policies including packages for OAuth1a and OAuth2.
  • Serialization that supports both ORM and non-ORM data sources.
  • Customizable all the way down - just use regular function-based views if you don't need the more powerful features.
  • Extensive documentation, and great community support.
  • Used and trusted by internationally recognised companies including Mozilla, Red Hat, Heroku, and Eventbrite.

First we need to update our requirements.txt file with dependencies

# Django itself
django>=4.0.0 

# InterSystems IRIS driver for Django, and DB-API driver from InterSystems
django-iris=>0.1.13
https://raw.githubusercontent.com/intersystems-community/iris-driver-distribution/main/DB-API/intersystems_irispython-3.2.0-py3-none-any.whl 

# Django REST Framework and its optional dependencies
djangorestframework>=3.4.4
# Markdown support for the browsable API.
markdown>=3.0.0 
# Filtering support
django-filter>=1.0.1

And install them

python install -r requirements.txt

First draft of API

Update urls.py file to this. Here we say, that from the root for our api as api/, so any requests to http://localhost:8000/api/ will be used as root for our API requests

from django.contrib import admin
from django.urls import path, include
from rest_framework import routers

router = routers.DefaultRouter()

urlpatterns = [
    path('api/', include(router.urls)),
    path('admin/', admin.site.urls),
    path('api-auth/', include('rest_framework.urls')),
]

Django REST Framework, has embedded UI for API, when server running in development mode with DEBUG=True in settings.py. And we can open this URL

All working, even did not even define anything, just connected that framework to url. It does support authorization, for requests required authorization. 

$ curl http://127.0.0.1:8000/api/
{}

Do define an API for project, we will use a few features from REST Framework at minimum

  • Serializers - allow complex data such as querysets and model instances to be converted to native Python datatypes that can then be easily rendered into JSONXML or other content types. Serializers also provide deserialization, allowing parsed data to be converted back into complex types, after first validating the incoming data.
  • ViewSet - allows you to combine the logic for a set of related views in a single class

Let's add an endpoint for our posts. Very simple, yet. Look at the updated content of urls.py 

from django.contrib import admin
from django.urls import path, include
from rest_framework import routers, serializers, viewsets
from .models import CommunityPost

router = routers.DefaultRouter()

class CommunityPostSerializer(serializers.HyperlinkedModelSerializer):
    class Meta:
        # class with model
        model = CommunityPost
        # list of fields to show, or just '__all__'
        fields = '__all__'
# ViewSets define the view behavior.
class CommunityPostViewSet(viewsets.ModelViewSet):
    queryset = CommunityPost.objects.all()
    serializer_class = CommunityPostSerializer

# connect it with API
router.register(r'posts', CommunityPostViewSet)

urlpatterns = [
    path('api/', include(router.urls)),
    path('admin/', admin.site.urls),
    path('api-auth/', include('rest_framework.urls')),
]

And it now appeared in the web UI

Just click on the link here, and you will the response for it

Scroll to the end, and you will find a generated form for new items, which can be added by POST request. All the fields are suitable for the type of properties

In the list of items, you may click on any item's URL, and see this. Just only this item in response, and an editing form with PUT request

Authentication

And you already can do change the data, by PUT or POST. The need of authorization not activated, yet. REST Framework offers various combination of authentications for use, so, you can open some of the resources for anonymous access read-only. And authenticate to be able to do any changes. Or completely close any access. We just configure, read-only for anonymous, and require authentication for any changes. To do it, just add this lines to settings.py

REST_FRAMEWORK = {
    # Use Django's standard `django.contrib.auth` permissions,
    # or allow read-only access for unauthenticated users.
    'DEFAULT_PERMISSION_CLASSES': [
        'rest_framework.permissions.DjangoModelPermissionsOrAnonReadOnly',
    ],
}

With this, you will not see form anymore until you'll login, with the username and password for instance created previously for Django Administration.

Pagination

By default, it does not have pagination, but we can easily add it to any list queries. Update REST_FRAMEWORK variable in settings.py. Setup pagination class, and default page size

REST_FRAMEWORK = {
...
    'DEFAULT_PAGINATION_CLASS': 'rest_framework.pagination.LimitOffsetPagination',
    'PAGE_SIZE': 10,
...
}

In result, it slightly changed the resulting JSON, added relevant items, such as, next and previous pages links, as well, as amount of all items. And with Web UI you can go through the pages.

Filtering and Searching

It is is also, quite simple to add filtering capabilities, and searching. Update REST_FRAMEWORK variable in settings.py

REST_FRAMEWORK = {
... 
    'DEFAULT_FILTER_BACKENDS': [
        'django_filters.rest_framework.DjangoFilterBackend',
        'rest_framework.filters.SearchFilter',
    ],
...
]

And update CommunityPostViewSet with a list of fields for filtering and for search

class CommunityPostViewSet(viewsets.ModelViewSet):
    queryset = CommunityPost.objects.all()
    serializer_class = CommunityPostSerializer
    filterset_fields = ['posttype', 'lang', 'published']
    search_fields = ['name',]

And it's working right from the Web UI

And after all, we have fully functional REST API, just for this one resource, yet. Quite simple at the moment, but it's possible to make many customization, connect other resources and link them.

Discussion (0)1
Log in or sign up to continue