mirror of
https://github.com/inventree/InvenTree
synced 2024-08-30 18:33:04 +00:00
Optionally paginate the StockList table on the server
- This makes the bootstrap table interface SO FREAKING MUCH FASTER - Search is now performed on the server too!
This commit is contained in:
parent
5cdae04c62
commit
8ce7b572cc
@ -40,6 +40,7 @@ from decimal import Decimal, InvalidOperation
|
|||||||
|
|
||||||
from datetime import datetime, timedelta
|
from datetime import datetime, timedelta
|
||||||
|
|
||||||
|
from rest_framework.pagination import LimitOffsetPagination
|
||||||
from rest_framework.serializers import ValidationError
|
from rest_framework.serializers import ValidationError
|
||||||
from rest_framework.views import APIView
|
from rest_framework.views import APIView
|
||||||
from rest_framework.response import Response
|
from rest_framework.response import Response
|
||||||
@ -337,6 +338,8 @@ class StockList(generics.ListCreateAPIView):
|
|||||||
serializer_class = StockItemSerializer
|
serializer_class = StockItemSerializer
|
||||||
queryset = StockItem.objects.all()
|
queryset = StockItem.objects.all()
|
||||||
|
|
||||||
|
pagination_class = LimitOffsetPagination
|
||||||
|
|
||||||
def create(self, request, *args, **kwargs):
|
def create(self, request, *args, **kwargs):
|
||||||
"""
|
"""
|
||||||
Create a new StockItem object via the API.
|
Create a new StockItem object via the API.
|
||||||
@ -381,6 +384,12 @@ class StockList(generics.ListCreateAPIView):
|
|||||||
|
|
||||||
queryset = self.filter_queryset(self.get_queryset())
|
queryset = self.filter_queryset(self.get_queryset())
|
||||||
|
|
||||||
|
page = self.paginate_queryset(queryset)
|
||||||
|
|
||||||
|
if page is not None:
|
||||||
|
|
||||||
|
serializer = self.get_serializer(page, many=True)
|
||||||
|
else:
|
||||||
serializer = self.get_serializer(queryset, many=True)
|
serializer = self.get_serializer(queryset, many=True)
|
||||||
|
|
||||||
data = serializer.data
|
data = serializer.data
|
||||||
@ -465,6 +474,8 @@ class StockList(generics.ListCreateAPIView):
|
|||||||
Note: b) is about 100x quicker than a), because the DRF framework adds a lot of cruft
|
Note: b) is about 100x quicker than a), because the DRF framework adds a lot of cruft
|
||||||
"""
|
"""
|
||||||
|
|
||||||
|
if page is not None:
|
||||||
|
return self.get_paginated_response(data)
|
||||||
if request.is_ajax():
|
if request.is_ajax():
|
||||||
return JsonResponse(data, safe=False)
|
return JsonResponse(data, safe=False)
|
||||||
else:
|
else:
|
||||||
@ -806,19 +817,6 @@ class StockList(generics.ListCreateAPIView):
|
|||||||
print("After error:", str(updated_after))
|
print("After error:", str(updated_after))
|
||||||
pass
|
pass
|
||||||
|
|
||||||
# Limit number of results
|
|
||||||
limit = params.get('limit', None)
|
|
||||||
|
|
||||||
if limit is not None:
|
|
||||||
try:
|
|
||||||
limit = int(limit)
|
|
||||||
|
|
||||||
if limit > 0:
|
|
||||||
queryset = queryset[:limit]
|
|
||||||
|
|
||||||
except (ValueError):
|
|
||||||
pass
|
|
||||||
|
|
||||||
# Also ensure that we pre-fecth all the related items
|
# Also ensure that we pre-fecth all the related items
|
||||||
queryset = queryset.prefetch_related(
|
queryset = queryset.prefetch_related(
|
||||||
'part',
|
'part',
|
||||||
@ -839,9 +837,12 @@ class StockList(generics.ListCreateAPIView):
|
|||||||
|
|
||||||
ordering_fields = [
|
ordering_fields = [
|
||||||
'part__name',
|
'part__name',
|
||||||
|
'part__IPN',
|
||||||
'updated',
|
'updated',
|
||||||
'stocktake_date',
|
'stocktake_date',
|
||||||
'expiry_date',
|
'expiry_date',
|
||||||
|
'quantity',
|
||||||
|
'status',
|
||||||
]
|
]
|
||||||
|
|
||||||
ordering = ['part__name']
|
ordering = ['part__name']
|
||||||
@ -851,7 +852,8 @@ class StockList(generics.ListCreateAPIView):
|
|||||||
'batch',
|
'batch',
|
||||||
'part__name',
|
'part__name',
|
||||||
'part__IPN',
|
'part__IPN',
|
||||||
'part__description'
|
'part__description',
|
||||||
|
'location__name',
|
||||||
]
|
]
|
||||||
|
|
||||||
|
|
||||||
|
@ -325,6 +325,12 @@ function loadStockTable(table, options) {
|
|||||||
grouping = options.grouping;
|
grouping = options.grouping;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Explicitly disable part grouping functionality
|
||||||
|
// Might be able to add this in later on,
|
||||||
|
// but there is a bug which makes this crash if paginating on the server side.
|
||||||
|
// Ref: https://github.com/wenzhixin/bootstrap-table/issues/3250
|
||||||
|
grouping = false;
|
||||||
|
|
||||||
table.inventreeTable({
|
table.inventreeTable({
|
||||||
method: 'get',
|
method: 'get',
|
||||||
formatNoMatches: function() {
|
formatNoMatches: function() {
|
||||||
@ -332,7 +338,7 @@ function loadStockTable(table, options) {
|
|||||||
},
|
},
|
||||||
url: options.url || "{% url 'api-stock-list' %}",
|
url: options.url || "{% url 'api-stock-list' %}",
|
||||||
queryParams: filters,
|
queryParams: filters,
|
||||||
customSort: customGroupSorter,
|
sidePagination: 'server',
|
||||||
name: 'stock',
|
name: 'stock',
|
||||||
original: original,
|
original: original,
|
||||||
showColumns: true,
|
showColumns: true,
|
||||||
@ -516,6 +522,7 @@ function loadStockTable(table, options) {
|
|||||||
{
|
{
|
||||||
field: 'part_detail.full_name',
|
field: 'part_detail.full_name',
|
||||||
title: '{% trans "Part" %}',
|
title: '{% trans "Part" %}',
|
||||||
|
sortName: 'part__name',
|
||||||
sortable: true,
|
sortable: true,
|
||||||
switchable: false,
|
switchable: false,
|
||||||
formatter: function(value, row, index, field) {
|
formatter: function(value, row, index, field) {
|
||||||
@ -534,6 +541,7 @@ function loadStockTable(table, options) {
|
|||||||
{
|
{
|
||||||
field: 'part_detail.IPN',
|
field: 'part_detail.IPN',
|
||||||
title: 'IPN',
|
title: 'IPN',
|
||||||
|
sortName: 'part__IPN',
|
||||||
sortable: true,
|
sortable: true,
|
||||||
formatter: function(value, row, index, field) {
|
formatter: function(value, row, index, field) {
|
||||||
return row.part_detail.IPN;
|
return row.part_detail.IPN;
|
||||||
@ -542,7 +550,6 @@ function loadStockTable(table, options) {
|
|||||||
{
|
{
|
||||||
field: 'part_detail.description',
|
field: 'part_detail.description',
|
||||||
title: '{% trans "Description" %}',
|
title: '{% trans "Description" %}',
|
||||||
sortable: true,
|
|
||||||
formatter: function(value, row, index, field) {
|
formatter: function(value, row, index, field) {
|
||||||
return row.part_detail.description;
|
return row.part_detail.description;
|
||||||
}
|
}
|
||||||
@ -654,8 +661,6 @@ function loadStockTable(table, options) {
|
|||||||
{
|
{
|
||||||
field: 'packaging',
|
field: 'packaging',
|
||||||
title: '{% trans "Packaging" %}',
|
title: '{% trans "Packaging" %}',
|
||||||
sortable: true,
|
|
||||||
searchable: true,
|
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
field: 'notes',
|
field: 'notes',
|
||||||
|
@ -1,5 +1,6 @@
|
|||||||
{% load i18n %}
|
{% load i18n %}
|
||||||
{% load status_codes %}
|
{% load status_codes %}
|
||||||
|
{% load inventree_extras %}
|
||||||
|
|
||||||
{% include "status_codes.html" with label='stock' options=StockStatus.list %}
|
{% include "status_codes.html" with label='stock' options=StockStatus.list %}
|
||||||
{% include "status_codes.html" with label='build' options=BuildStatus.list %}
|
{% include "status_codes.html" with label='build' options=BuildStatus.list %}
|
||||||
@ -110,6 +111,8 @@ function getAvailableTableFilters(tableKey) {
|
|||||||
title: '{% trans "Depleted" %}',
|
title: '{% trans "Depleted" %}',
|
||||||
description: '{% trans "Show stock items which are depleted" %}',
|
description: '{% trans "Show stock items which are depleted" %}',
|
||||||
},
|
},
|
||||||
|
{% settings_value "STOCK_ENABLE_EXPIRY" as expiry %}
|
||||||
|
{% if expiry %}
|
||||||
expired: {
|
expired: {
|
||||||
type: 'bool',
|
type: 'bool',
|
||||||
title: '{% trans "Expired" %}',
|
title: '{% trans "Expired" %}',
|
||||||
@ -120,6 +123,7 @@ function getAvailableTableFilters(tableKey) {
|
|||||||
title: '{% trans "Stale" %}',
|
title: '{% trans "Stale" %}',
|
||||||
description: '{% trans "Show stock which is close to expiring" %}',
|
description: '{% trans "Show stock which is close to expiring" %}',
|
||||||
},
|
},
|
||||||
|
{% endif %}
|
||||||
in_stock: {
|
in_stock: {
|
||||||
type: 'bool',
|
type: 'bool',
|
||||||
title: '{% trans "In Stock" %}',
|
title: '{% trans "In Stock" %}',
|
||||||
|
@ -93,7 +93,14 @@ function reloadTable(table, filters) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
options.queryParams = params;
|
options.queryParams = function(tableParams) {
|
||||||
|
|
||||||
|
for (key in params) {
|
||||||
|
tableParams[key] = params[key];
|
||||||
|
}
|
||||||
|
|
||||||
|
return tableParams;
|
||||||
|
}
|
||||||
|
|
||||||
table.bootstrapTable('refreshOptions', options);
|
table.bootstrapTable('refreshOptions', options);
|
||||||
table.bootstrapTable('refresh');
|
table.bootstrapTable('refresh');
|
||||||
@ -126,9 +133,45 @@ $.fn.inventreeTable = function(options) {
|
|||||||
|
|
||||||
var varName = tableName + '-pagesize';
|
var varName = tableName + '-pagesize';
|
||||||
|
|
||||||
|
// Pagingation options (can be server-side or client-side as specified by the caller)
|
||||||
options.pagination = true;
|
options.pagination = true;
|
||||||
|
options.paginationVAlign = 'both';
|
||||||
options.pageSize = inventreeLoad(varName, 25);
|
options.pageSize = inventreeLoad(varName, 25);
|
||||||
options.pageList = [25, 50, 100, 250, 'all'];
|
options.pageList = [25, 50, 100, 250, 'all'];
|
||||||
|
options.totalField = 'count';
|
||||||
|
options.dataField = 'results';
|
||||||
|
|
||||||
|
// Extract query params
|
||||||
|
var filters = options.queryParams || options.filters || {};
|
||||||
|
|
||||||
|
options.queryParams = function(params) {
|
||||||
|
for (var key in filters) {
|
||||||
|
params[key] = filters[key];
|
||||||
|
}
|
||||||
|
|
||||||
|
// Override the way that we ask the server to sort results
|
||||||
|
// It seems bootstrap-table does not offer a "native" way to do this...
|
||||||
|
if ('sort' in params) {
|
||||||
|
var order = params['order'];
|
||||||
|
|
||||||
|
var ordering = params['sort'] || null;
|
||||||
|
|
||||||
|
if (ordering) {
|
||||||
|
|
||||||
|
if (order == 'desc') {
|
||||||
|
ordering = `-${ordering}`;
|
||||||
|
}
|
||||||
|
|
||||||
|
params['ordering'] = ordering;
|
||||||
|
}
|
||||||
|
|
||||||
|
delete params['sort'];
|
||||||
|
delete params['order'];
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
return params;
|
||||||
|
}
|
||||||
|
|
||||||
options.rememberOrder = true;
|
options.rememberOrder = true;
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user