In Django how can I list a Queryset in one view/template generated by another view?
I'm developing a tracking system that has 2 main datasets Orders
and Shipments
. Focussing on Orders
I want to enable users to enter any combination of field data and then display the resulting list using pagination. To achieve this I have 2 views/templates. One, search_orders
, displays a form that is, essentially, a list of the majority of the dataset fields. The other, list_orders
, displays a list of the selected orders. This all works fine if I just render list_orders
from search_orders
without any pagination but, in order to get pagination I (believe that I) need search_orders
to redirect to list_orders
and, so far, I've been unable to do that.
Search_orders view:
@login_required
def search_orders(request):
if request.method == 'POST' and len(request.POST) > 1:
orders = Order.objects.all()
msg = ''
fields_selected = ''
for fld in request.POST:
if fld == 'orderid' and request.POST.get('orderid'):
msg += f'{fld} - {request.POST.get('orderid')} and '
fields_selected = True
orders = orders.filter(orderid__icontains=request.POST.get('orderid'))
if fld == 'bookingtype' and request.POST.get('bookingtype'):
msg += f'{fld} - {request.POST.get('bookingtype')} and '
fields_selected = True
orders = orders.filter(bookingtype__icontains=request.POST.get('bookingtype'))
if fld == 'shp' and request.POST.get('shp'):
msg += f'{fld} - {request.POST.get('shp')} and '
fields_selected = True
orders = orders.filter(shp__icontains=request.POST.get('shp'))
if fld == 'con' and request.POST.get('con'):
msg += f'{fld} - {request.POST.get('con')} and '
fields_selected = True
orders = orders.filter(con__icontains=request.POST.get('con'))
if fld == 'booked1' and request.POST.get('booked1'):
dt = datetime.datetime.strptime(request.POST.get('booked1'), "%Y-%m-%d").strftime("%d-%b-%y")
msg += f'{fld} - {dt} and '
fields_selected = True
orders = orders.filter(booked__gte=request.POST.get('booked1'))
if fld == 'booked2' and request.POST.get('booked2'):
msg += f'{fld} - {request.POST.get('booked2')} and '
fields_selected = True
orders = orders.filter(booked__lte=request.POST.get('booked2'))
if fld == 'matavail1' and request.POST.get('matavail1'):
msg += f'{fld} - {request.POST.get('matavail1')} and '
fields_selected = True
orders = orders.filter(matavail__gte=request.POST.get('matavail1'))
if fld == 'matavail2' and request.POST.get('matavail2'):
msg += f'{fld} - {request.POST.get('matavail2')} and '
fields_selected = True
orders = orders.filter(matavail__lte=request.POST.get('matavail2'))
if fld == 'reqd1' and request.POST.get('reqd1'):
msg += f'{fld} - {request.POST.get('reqd1')} and '
fields_selected = True
orders = orders.filter(reqd__gte=request.POST.get('reqd1'))
if fld == 'reqd2' and request.POST.get('reqd2'):
msg += f'{fld} - {request.POST.get('reqd2')} anda'
fields_selected = True
orders = orders.filter(reqd__lte=request.POST.get('reqd2'))
if fld == 'origin' and request.POST.get('origin'):
msg += f'{fld} - {request.POST.get('origin')} and '
fields_selected = True
origin = Country.objects.filter(countrycode=request.POST.get('origin'))
orders = orders.filter(origin=origin[0])
if fld == 'destn' and request.POST.get('destn'):
msg += f'{fld} - {request.POST.get('destn')} and '
fields_selected = True
destn = Country.objects.filter(countrycode=request.POST.get('destn'))
orders = orders.filter(destn=destn[0])
if fld == 'shpid' and request.POST.get('shpid'):
msg += f'{fld} - {request.POST.get('shpid')} and '
fields_selected = True
orders = orders.filter(shipment__shpid__icontains=request.POST.get('shpid')).select_related(
'shipment')
if fields_selected:
orders.order_by('-orderid')
#paginator = Paginator(orders, 10) <---- pagination not working
#page_number = request.GET.get('page')
#print(f'Orders selected = {orders}')
#print(f'page_number = {page_number}')
#orders = paginator.page(page_number)
messages.success(request, f'Search criteria: {msg[:-5]}')
else:
orders = Order.objects.none()
messages.success(request, "No field selections entered")
print(f'Orders selected = {orders}')
#return redirect(reverse('tracker:list_orders',kwargs={'action':msg[:-5],'orders':orders}))
#return redirect('tracker:list_orders',kwargs={'action':msg[:-5],'orders':orders})
#return redirect('tracker:list_orders',items)
return render(request, 'tracker/list_orders.html',{'action':msg[:-5],'orders':orders})
else:
#messages.success(request, 'Not in true POST')
return render(request,'tracker/search_orders.html')
List_orders view:
@login_required
def list_orders(request, action):
#orders = Order.objects.all()
if action == 'today':
today = timezone.now().date()
orders = Order.objects.filter(booked=today)
elif action == 'open':
orders = Order.objects.all().exclude(closed=True).order_by('-booked')
paginator = Paginator(orders,16)
page_number = request.GET.get('page',1)
orders = paginator.page(page_number)
return render(request,'tracker/list_orders.html',{'orders':orders,'action':action})
urls.py
app_name = 'tracker'
urlpatterns = [
path("about/", views.about, name="about"),
path("mainmenu/", views.mainmenu, name="mainmenu"),
path("search_orders/", views.search_orders, name="search_orders"),
path("list_orders/<str:action>/", views.list_orders, name="list_orders"),
...
How can I pass the filtered queryset through to list_orders
for paginated display or, alternativery, pass the selected query fields through to list_orders
such that list_orders
can do the filtering?
(In the interests of brevity I've omitted the relevant templates but can add them if desired.)
The answer that works for me is to convert the resultant QueryDict
generated by search_orders
, firstly by converting to binary using pickle
and then converting the resulting binary tobase64
and then redirect to list_orders
with the pickled/base64'd output as a single string parameter.
On the receiving end, in list_orders
, the first thing to do is to reverse the pickling/base64'ing process to convert the parameter back to a QueryDict
and then to process that - but that processing takes place in list_orders
rather than in search_orders
.
So, in essence, the search page/view is used only to capture the filtering input, the listing page/view does the actual processing.