You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何基于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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.04.29 17:47:35