[PYTHON] I want to create an API that returns a model with a recursive relationship in the Django REST Framework

Goal of this article

Consider the case of a model with recursive relations (such as a tree structure). Create an API that recursively returns json using Django REST Framework.

environment

MacOS(10.11.6 / ElCapitane) Python 3.5.2 Django 1.10.4 DjangoRESTFramework 3.5.3

Model

Defines a model with a recursive relationship. Consider a model that has more subcategories within the category. The reverse relation name is subcategories.

models.py


class Category(models.Model):
    parentCategory = models.ForeignKey('self', blank=True, null=True, related_name='subcategories')
    name = models.CharField(max_length=200)
    description = models.CharField(max_length=500)

Serializer Define SubCategorySerializer that inherits ModelSerializer, and overwrite subcategories, which is the inverse relation of Category, with SubCategorySerializer. At this time, parentCategory should return serializers.PrimaryKeyRelatedField ().

serializers.py


class SubCategorySerializer(serializers.ModelSerializer):
    class Meta:
        model = Category
        fields = ('name', 'description')

class CategorySerializer(serializers.ModelSerializer):
    parentCategory = serializers.PrimaryKeyRelatedField()
    subcategories = serializers.SubCategorySerializer()

    class Meta:
        model = Category
        fields = ('parentCategory', 'name', 'description', 'subcategories')

View

It is OK if you specify CategorySerializer for Serializer in View. The query set should be a query that can uniquely retrieve the top hierarchy. If you use get (), you will get the object, so use filter () that returns a query. (For example, define is_root in the model and get it with filter (is_root = True))

view.py


class CategoryListViewSet(viewsets.ModelViewSet):
    queryset = Category.objects.filter(id='e.g...root_category_id').prefetch_related('subcategories__subcategories')
    serializer_class = CategorySeriarizer

Another way

It can also be realized by defining and returning the following RecursiveField. I think this is also good because it is flexible.

serializers.py


class RecursiveField(serializers.Serializer):
    def to_representation(self, value):
        serializer = self.parent.parent.__class__(value, context=self.context)
        return serializer.data

class CategorySerializer(serializers.Serializer):
    subcategories = RecursiveField(many=True)

    class Meta:
        model = Comment
        fields = ('parendCategory','name', 'description', 'subcategories')

result

It is a different model from the above example, but if it is a file system model with a simple tree structure and recursive relations, this json will be returned.

hoge.json


[
    {
        "name": "RootDirectory",
        "is_root": true,
        "is_dir": true,
        "parent_file": null,
        "child_files": [
            {
                "name": "root_file",
                "is_root": false,
                "is_dir": false,
                "parent_file": 34,
                "child_files": []
            },
            {
                "name": "TestDir",
                "is_root": false,
                "is_dir": true,
                "parent_file": 34,
                "child_files": [
                    {
                        "name": "test.zip",
                        "is_root": false,
                        "is_dir": false,
                        "parent_file": 35,
                        "child_files": []
                    },
                    {
                        "name": "test_dir_file.png ",
                        "is_root": false,
                        "is_dir": false,
                        "parent_file": 35,
                        "child_files": []
                    }
                ]
            }
        ]
    }
]

Let's all have fun with Django and create a REST API! !!

reference

http://www.django-rest-framework.org/api-guide/relations/#custom-relational-fields http://stackoverflow.com/questions/13376894/django-rest-framework-nested-self-referential-objects

Recommended Posts

I want to create an API that returns a model with a recursive relationship in the Django REST Framework
Create a REST API to operate dynamodb with the Django REST Framework
Creating an API that returns negative-positive inference results using BERT in the Django REST framework
How to create a Rest Api in Django
Create a Todo app with the Django REST framework
I made an API with Docker that returns the predicted value of the machine learning model
Create an API that returns data from a model using turicreate
Create REST API that returns the current time with Python3 + Falcon
I want to create a graph with wavy lines omitted in the middle with matplotlib (I want to manipulate the impression)
I want to easily create a Noise Model
I want to create a window in Python
I want to create a priority queue that can be updated in Python (2.7)
Create a REST API using the model learned in Lobe and TensorFlow Serving.
Create a filter to get an Access Token in the Graph API (Flask)
I tried to create a model with the sample of Amazon SageMaker Autopilot
Create a Todo app with Django REST Framework + Angular
I tried to create a table only with Django
I want to transition with a button in flask
When you want to filter with Django REST framework
I want to work with a robot in python.
I want to manually create a legend with matplotlib
Develop a web API that returns data stored in DB with Django and SQLite
I want to create a lunch database [EP1] Django study for the first time
I want to create a lunch database [EP1-4] Django study for the first time
I want to get an error message in Japanese with django Password Change Form
Create an API with Django
How to write custom validations in the Django REST Framework
The first API to make with python Djnago REST framework
I want to make a blog editor with django admin
I can't log in to the admin page with Django3
Tornado-Let's create a Web API that easily returns JSON with JSON
Create a web API that can deliver images with Django
I want to create a Dockerfile for the time being.
I tried to create an article in Wiki.js with SQLAlchemy
I tried to create a RESTful API by connecting the explosive Python framework FastAPI to MySQL.
A script that makes it easy to create rich menus with the LINE Messaging API
How to create a record by pasting a relation to the inheriting source Model in the Model inherited by Django
A story that makes it easier to see Model debugging in the Django + SQLAlchemy environment
A story that I wanted to display the division result (%) on HTML with an application using django [Beginner learns python with a reference book in one hand]
I want to use a wildcard that I want to shell with Python remove
Create an alias for Route53 to CloudFront with the AWS API
[Python / Django] Create a web API that responds in JSON format
Qiskit: I want to create a circuit that creates arbitrary states! !!
How to create a heatmap with an arbitrary domain in Python
I want to create a system to prevent forgetting to tighten the key 1
I want to create a pipfile and reflect it in docker
Try to create a Qiita article with REST API [Environmental preparation]
Create an application that just searches using the Google Custom Search API with Python 3.3.1 in Bottle
[Django] What to do if the model you want to create has a large number of fields
I came up with a way to create a 3D model from a photo Part 01 Creating an environment
A story that didn't work when I tried to log in with the Python requests module
A story that I had a hard time trying to create an "app that converts images like paintings" with the first web application
I want to improve efficiency with Python even in the experimental system (5) I want to send a notification at the end of the experiment with the slack API
Implementation of custom user model authentication in Django REST Framework with djoser
A note that you want to manually decorate the parameters passed in the Django template form item by item
Create RESTful APIs with Django Rest Framework
I made a POST script to create an issue on Github and register it in the Project
I want to be healed by Mia Nanasawa's image. In such a case, hit the Twitter API ♪
I want to print in a comprehension
[For beginners] I want to get the index of an element that satisfies a certain conditional expression
(Matplotlib) I want to draw a graph with a size specified in pixels