如何基于Vuex与Django Rest Framework实现Quasar QTable的服务端分页?
解决Quasar QTable + Vuex + Django DRF的服务端分页问题
你现在的核心问题是没有把QTable的分页参数变化和后端数据请求关联起来,尤其是没利用好QTable的@request事件触发新的分页数据获取,另外直接绑定Vuex的pagination到v-model:pagination也不符合Vuex的状态管理规范(不能直接修改state)。咱们一步步来修复:
1. 调整Vue组件代码
添加@request事件监听,用本地分页对象和QTable交互,避免直接修改Vuex state:
<template> <q-table title="Matches" :rows="matches.results" :columns="columns" :pagination="localPagination" @request="onRequest" row-key="id" > <template v-slot:body-cell-actions="props"> <q-td :props="props"> <router-link class="action-links" :to="{ name: 'Match', params: { id: props.row.id } }">Details</router-link> </q-td> </template> </q-table> </template> <script> import { mapState, mapActions } from 'vuex' export default { data() { return { columns: [ { name: 'team', label: 'Team', align: 'left', field: 'team', sortable: true, required: true }, { name: 'date', label: 'Date', align: 'left', field: 'formatted_date', sortable: true }, { name: 'actions', label: 'Actions', align: 'left', field: '' } ], localPagination: { sortBy: 'desc', descending: false, page: 1, rowsPerPage: 1, rowsNumber: 0 } } }, mounted() { this.initPagination() this.getMatches() }, computed: { ...mapState({ matches: state => state.matches.matches, pagination: state => state.matches.pagination }) }, methods: { ...mapActions(['matches/getMatches']), initPagination() { this.localPagination = { ...this.pagination } }, onRequest(paginationParams) { this.localPagination = paginationParams this['matches/getMatches'](paginationParams) } }, watch: { pagination(newVal) { this.localPagination.rowsNumber = newVal.rowsNumber } } } </script>
2. 修改Vuex状态管理代码
更新action接收分页参数,同时修改mutation同步所有分页属性:
import { api } from 'boot/axios' export const state = { matches: [], pagination: { sortBy: 'desc', descending: false, page: 1, rowsPerPage: 1, rowsNumber: 0 } } export const mutations = { SET_MATCHES(state, { matches, pagination }) { state.matches = matches state.pagination = { ...state.pagination, ...pagination, rowsNumber: matches.count } } } export const actions = { getMatches({ commit }, paginationParams = state.pagination) { const { page, rowsPerPage, sortBy, descending } = paginationParams const sortParam = descending ? `-${sortBy}` : sortBy api .get(`/api/v1/matches/`, { params: { page, page_size: rowsPerPage, ordering: sortParam } }) .then(response => { commit('SET_MATCHES', { matches: response.data, pagination: paginationParams }) }) } }
3. 调整Django DRF分页配置
允许前端动态设置每页行数:
from rest_framework.pagination import PageNumberPagination class MatchPagination(PageNumberPagination): page_size = 2 # 默认每页2条 page_size_query_param = 'page_size' # 开启前端自定义每页行数 max_page_size = 100 # 可选:限制最大每页行数,防止恶意请求 class MatchViewSet(viewsets.ModelViewSet): serializer_class = MatchSerializer queryset = Match.objects.all() pagination_class = MatchPagination
关键逻辑说明
- QTable的
@request事件:用户切换页码、修改每页行数、点击排序时,该事件会自动触发并传递最新分页参数,这是服务端分页的核心触发点。 - Vuex状态规范:通过本地分页对象和QTable交互,再将参数传给action,避免直接修改Vuex state,符合单向数据流原则。
- DRF参数适配:DRF的
PageNumberPagination默认支持page参数,通过page_size_query_param开启page_size参数支持,排序用ordering参数(前缀-表示降序)。
这样调整后,每页行数设置、分页切换、排序功能都能正常工作,完全符合服务端分页的逻辑。
内容的提问来源于stack exchange,提问作者kkscott
相关产品推荐
相关产品推荐

