对于我的项目,我开始将Laravel用于api而不是切换到Django / django rest框架,这样做是为了提高查询大数据的速度。
现在我遇到以下情况: 我得到了一个具有“主题”并且具有递归关系的“组”。
现在,一个小组可以拥有2000多个科目(包括后代科目),而父级科目可以拥有+/- 30个科目。
这是我的代码:
序列化器
class RecursiveField(serializers.Serializer):
def to_representation(self, value):
serializer = self.parent.parent.__class__(value, context=self.context)
return serializer.data
class SubjectSerializer(serializers.ModelSerializer):
parent_of = RecursiveField(many=True, read_only=True)
class Meta:
model = Subject
fields = ("id", "name", "parent_of", "parent")
class GroupSerializer(serializers.ModelSerializer):
subjects = SubjectSerializer(many=True, read_only=True)
class Meta:
model = Group
fields = ("id", "name", "subjects")
def setup_eager_loading(cls, queryset):
return queryset.prefetch_related("subjects")
观看次数
class GroupViewSet(ModelViewSet):
class Paginator(BasePaginator):
model = Group
queryset = Group.objects.all()
serializer_class = serializers.GroupSerializer
pagination_class = Paginator
def get_queryset(self):
return self.get_serializer().setup_eager_loading(GroupViewSet.queryset)
我使用laravel api测试了相同的请求,它的速度更快,但仍然很慢,但是还可以(5-10秒)。使用django rest框架时,速度太慢(大约1分钟+/-),而这仅仅是一个包含2500个主题的小组的页面。
我知道RecursiveField类花了很长时间,因为当我删除该查询时,不到2秒即可完成。所以我的问题是最主要的原因,因为它创建了一个递归关系(我怀疑)?还是因为我不预取?
当然,什么是最好的方法?
谢谢
答案 0 :(得分:0)
您有几种选择,但是我认为没有什么很棒。 Django对递归查询的支持不是很好。
root
ForeignKey来标识根主题。这将使您相当容易地抓住树上的所有主题。然后,您必须将它们安排在您的“视图/视图集”中以适应顺序(如果需要)。raw()
和数据库的递归功能来获取模型。这将需要原始SQL,并且可能难以维护。django_cte
。我已经在我的一个项目中使用过此功能进行了一些查询,但是我并不喜欢它。在空查询集上调用update()
会破坏某些功能。但是,它将起作用,并且不需要您使用原始SQL。 答案 1 :(得分:0)
问题不是DRF,而是数据结构本身。
django
中以递归方式查询所有祖先/后代的速度非常慢,您应该使用更有效的数据结构。
出于与我编写django-treenode
相同的原因,它执行树操作而不查询数据库。
您可以在此处阅读文档:https://github.com/fabiocaccamo/django-treenode