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.
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
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')
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! !!
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