我试图找到this(Google cache)
的解决方案我只能提出这样的解决方案:
import json
from mptt.utils import tree_item_iterator
from rest_framework import generics
from rest_framework.response import Response
from .models import Category
def tree_family_items_to_json(instances):
data = ''
channel = '"{}"'.format(instances[0].channel.slug)
for category, structure in tree_item_iterator(instances):
if structure['new_level']:
data += '{'
else:
data += '],'
data += '"channel": {}'.format(channel)
data += '},{'
data += '"slug": "{}",'.format(category.slug)
data += '"name": "{}",'.format(category.name)
data += '"subcategories": ['
for level in structure['closed_levels']:
data += '],'
data += '"channel": {}'.format(channel)
data += '}'
return json.loads(data)
class CategoryFamily(generics.RetrieveAPIView):
lookup_field = 'slug'
queryset = Category.objects.all()
def retrieve(self, request, *args, **kwargs):
instances = self.get_object().get_family()
json_data = tree_family_items_to_json(instances)
return Response(json_data)
关键是我使用了tree_item_iterator来自mptt,现在我正在寻找更有趣的东西。
适合需要一段时间。但现在确定了多久。
有什么想法吗?
答案 0 :(得分:3)
这是一种方法,以使树结构处于静止api:
# serializers.py
class CategoryTreeSerializer(ModelSerializer):
children = SerializerMethodField(source='get_children')
class Meta:
fields = ('children',) # add here rest of the fields from model
def get_children(self, obj):
children = self.context['children'].get(obj.id, [])
serializer = CategoryTreeSerializer(children, many=True, context=self.context)
return serializer.data
# views.py
class CategoryViewSet(viewsets.ModelViewSet):
queryset = Category.objects.all()
serializer_class = CategoryTreeSerializer
@detail_route()
def tree(self, request, pk=None):
"""
Detail route of an category that returns it's descendants in a tree structure.
"""
category = self.get_object()
descendants = category.get_descendants() # add here any select_related/prefetch_related fields to improve api performance
children_dict = defaultdict(list)
for descendant in descendants:
children_dict[descendant.get_parent().pk].append(descendant)
context = self.get_serializer_context()
context['children'] = children_dict
serializer = CategoryTreeSerializer(category, context=context)
return Response(serializer.data)
在我的情况下,你得到一个新的端点(取决于你的url),它将是这样的:category/<category_pk>/tree
,你可以在其中获得指定类别的树结构。
我们的想法是获取所有后代并为每个父级填充children_dict,这将传递给序列化程序的上下文,以避免多次查询。
答案 1 :(得分:0)
您可以使用djangorestframework-recursive来获得更多便利。
views.py
from rest_framework import viewsets, generics
from yourapp.serializers import CategorySerializer
from yourapp.models import Category
class CategoryViewSet(viewsets.ModelViewSet):
queryset = Category.objects.root_nodes()
serializer_class = CategorySerializer
serializers.py
from rest_framework import serializers
from yourapp.models import Category
from rest_framework_recursive.fields import RecursiveField
class CategorySerializer(serializers.ModelSerializer):
children = RecursiveField(many=True)
class Meta:
model = Category
fields = ['id', 'name', 'children']