Use Django REST Framework and OpenAPI to build React based dynamic user interface.
- Igor Miazek
- Feb 3, 2021
- 5 min read
Updated: Feb 14
In this tutorial I will focus on two things, how Django REST Framework (DRF) is creating OpenAPI-Specification (OAS) and how to use it to create dynamic user interface not related to any concrete endpoint. I will briefly tell about OpenAPI too.

All source code is here https://github.com/IOR88/DynamicApplicationInterface
Project environment
For this tutorial project, I am using python 3.6.9. So any python 3.6.*should work just fine. At this point You should have already virtualenv, if You have problems check this how to. The main benefit from virutalenv is to keep Your main python space clean.
Try with docker
If You have already docker installed You could do something like this.
The below will start docker container in interactive mode and remove it when exit the container. It will as well expose 8000 port for our server application.
$ docker run -p 8000:8000 --rm -it python:latest /bin/bash
Next when being in the container download this project source code, unzip it, install, run migration and run server
$ wget https://github.com/IOR88/DynamicApplicationInterface/archive/master.zip$ unzip master.zip$ cd DynamicApplicationInterface-master$ python setup.py install$ exampleproject-manage migrate$ exampleproject-manage runserver 0.0.0.0:8000
Ok we are done :), no the server home page is available here localhost:8000. If You have any problems let me know in comments.
Project Setup
All relevant information is here https://github.com/IOR88/DynamicApplicationInterface. Read README.md, in case of any problems I am here to help :).
As You may noticed I have used different command to install package. It looks like the api of latest python setup.py has changed. When You run
python setup.py install -e .
python is installing project dependencies and add project to PYTHONPATH so we can use it latter with import statement.
OpenAPI brief introduction
I think I would never describe it better as written already on specification github page:
It is important to note that thanks to it You provide a generic layer to your application, so your technical/programming implementation doesn’t matter as long as your REST API meets the requirements of specification.
Another benefit is that Your services maybe easily consumed by other services and because of specification standards You REST API is more reliable.
Example schema based on OpenAPI
Trigger this endpoint http://127.0.0.1:8000/schema/openapi in order to get OpenAPI schema.
If You are interested about some parts of OpenAPI check latest documentation. In this tutorial we will not cover the whole structure of OpenAPI specification.
For us the most important attribute for now is paths where we have definition of all resources and all actions we can do against resources.
/categories/: get: operationId: listCategoryModels description: '' parameters: - name: name required: false in: query description: name schema: type: string enum: - CARS - SHIPS - AIRPLANES responses: '200': content: application/json: schema: type: array items: properties: id: type: integer readOnly: true name: enum: - CARS - SHIPS - AIRPLANES required: - name description: ''
Each resource like /categories/ has definition of actions we can do with this resources, so we have get and post, other methods like get, putch, put and delete are available on another resource /categories/{id} which is referring to operations You can do for single object.
Path resource.get.parameters tell us how to ask for resources. Path resources.responses.status.content.contentType.schema tell us what we will get back. Based on above we can build dynamic components which will be responsible for querying and displaying resources.
Consuming OpenAPI schema and dynamic user interface
So first when app load we trigger request to load information about REST API resources.
axios .get('/schema/openapi?format=openapi-json') .then((response)=>{ this.setState({resources: new SchemaModel(response.data)}); })
For simplicity I have defined interface which contain all app logic about extracting information from schema.
class SchemaModel extends Model { constructor(data){ super(); this.data = data } getAllNamespacesToRead(){ return lodash .chain(this.data.paths) .entries .filter((entry)=>{ const [resource, value] = entry; const case1 = !lodash.isNil(value.get), case2 = resource.indexOf('{id}') === -1; if(case1 && case2) return entry; }).map((entry) => entry[0]).value() } namespace(namespace) { return lodash.get(this.data, `paths.${namespace}`); } properties(n) { const namespace = this.namespace(n); } parameters(n) { const namespace = this.namespace(n); return lodash .chain(namespace) .get('get.parameters') .map((p) => { let {schema} = p; return schema; }).value(); }}
Through the above class we can get information about each resource parameters and properties. We use this information latter to create filter component and table component.
Next when schema data is available we pass it to filters function component.
function Filters(props){ const {resources, onResourcesClicked} = props; const data = resources.getAllNamespacesToRead(); const onClick = (resource)=>{ onResourcesClicked(resource); }; return data.map((d)=>{ return React.createElement('div', {onClick: ()=> onClick(d)}, d); });}
Above we get all resources which define get action and render them, for simplicity we render each resource as div with attached on click event which will activate resource.
properties(n) { const namespace = this.namespace(n); return lodash .chain(namespace) .get(`get.responses.200.content.[application/json].schema.items.properties`) .entries() .map((p) => { const [name, value] = p; return {name, ...value}; }).value();}
Above we have SchemaModel properties method it will tell us what contain REST API response.
function Table(props){ const {resources, data, aresource} = props; const properties = resources.properties(aresource); return aresource ? data.map((d)=>{ const data = properties.map((p)=>{ return [p.name, d[p.name]]; }); return React.createElement('div', null, JSON.stringify(data)); }) : 'no data...'}
Above we have function based Table component, we get properties associated with active resources and display results. For simplicity we stringify all results.
Results

If everything is ok You should see this, nothing fancy sorry :). Although my main focus here was to show You how to use OpenAPI specification to build dynamic components.
No data yet

In order to add some dump data use django rest framework api interface.
Add few categories and items.

Summary
In this part we have build simple react application which consume REST API schema and provide user interface to display any resources that define get action.
Next:
In next part I plan to tell You more about how Django REST Framework build OpenAPI schema and how You can modify it to provide more advance logic. As a result we will be able to build filters which have dynamic options and all information will come from REST API schema. If You would be interested in anything specific let me know in comments ?
Benefits:
I have already built many applications with generic filtering layer. It is really cool that You can have one component that based on configuration changes its display and allow You to request for different resources. In filters You can handle many cases, build filters depending on its type(number input) and format(calendar). Finally You can build dynamic forms and tables based on schema only, schema can be used to make initial validation of forms before sending data to server.
What is even better, OpenAPI specification allow on extensions, so You can handle new cases that were not covered before or maybe are specific to the project You work on at the moment.