我不太明白QS在被重写时是如何被求值的。基于leedjango问题,我们可以在一个视图类中重写get_queryset。在这个例子中,我不太明白get_queryset方法何时返回QS求值。我们知道QS通常是如何被求值的,正如在eugene问题中所解释的那样。
例如,我有以下组件:前端将GET请求发送到适当的URL:
//Dashboard.js:
export default function Dashboard() {
const [tableData, setTableData] = useState([]);
const getUserSchools = () => {
getUser({ email: keycloak.email }).then((response) => {
const { data: users } = response;
if (users.length) {
const appUser = users[0];
axios
.get(`/api/school/list/?user_id=${appUser.id}`)
.then((data) => {
setTableData(data.data.results);
})
.catch((err) => {
/* eslint-disable-next-line */
console.error(err);
setTableData([]);
});
}
});
};
然后,它访问school-urls.py,查找与该URL相关的视图:
urlpatterns = [
url(r"^list/$", SchoolsList.as_view()),
]
SchoolsList是覆盖get_queryset并返回queryset的适当视图:
#list.py
class LargeResultsSetPagination(pagination.PageNumberPagination):
page_size = 10
page_size_query_param = 'page_size'
max_page_size = 100
class SchoolsList(generics.ListAPIView):
pagination_class = LargeResultsSetPagination
serializer_class = SchoolGetSerializer
def get_queryset(self):
queryset = School.objects.all()
user_id = self.request.query_params.get('user_id', None)
if (user_id is not None):
queryset = queryset.filter(user_id=user_id)
return queryset.order_by('id')
使用以下序列化程序:
#get.py
class SchoolGetSerializer(serializers.ModelSerializer):
nearest_community = SchoolCommunitySerializer(required=False)
nearest_post_secondary = SchoolPostSecondarySerializer(required=False)
regional_district = SchoolRegionalDistrictSerializer(required=False)
class Meta:
model = School
fields = (
"id",
"address",
"nearest_post_secondary",
"nearest_community",
"regional_district",
)
在上面的代码片段中,当查询集被求值时?
当从前端或 Postman 发送GET请求时,我可以看到返回了两次queryset,第一次几乎立即返回queryset。但是,GET请求直到50秒后才完成,再次计算并返回queryset(在这里我不知道如何计算)。手动执行的查询延迟750ms。这不是一个繁重的查询,它只是通过id选择一个记录。
你知道为什么get_queryset被命中并立即返回而不执行queryset,然后在50秒后查询数据库吗?我如何立即强制查询数据库?
**编辑:**QuerySet在执行Serializer之前会被求值,如果nearest_community和nearest_post_secondary字段有大量的查询,那么执行QuerySet会延迟,如果你只是简单的执行Serializer,那么你会立即得到响应。
谢谢
2条答案
按热度按时间hkmswyz61#
问题不在于查询,问题在于序列化器需要进行额外的查询来获取相关的对象。你应该在同一个查询中加载这些元素,使用**``**:
由于这些序列化程序可能会查询其他项,因此您甚至可能应该选择其他字段,但这些字段在您的问题中没有提到。
uelo1irk2#
查询集是惰性的,它们在你使用的时候被计算,而不是在你过滤、排序等等的时候(参见ModelManagers),使用它可以轻松进行批量管理(您的查询)。您需要检查连接到数据库的数量,特别是在循环中。这非常重要(不要做假设). Model.object.get_values()for get dictionaries可能会导致额外的成本,例如,您可以编写特定的Manager来修复它。如果您需要单独的东西,请使用模型方法。
我回答你的问题了吗?
这是错误的:
你做不到。查询还没完成。至少,做一下: