I am trying to download a CSV from the result of a search as an option. Meaning that the user can do a search and view the result in a template, and then download the csv for that search result if needed. The templates are not the issue, it's the views I need to resolve. I have the following views:
First is the search view
def binder_search(request):
if request.method == "POST":
searched = request.POST['searched']
binders_searched = Binders.objects.filter(Q(description__contains=searched) | Q(step__name__contains=searched) | Q(status__name__contains=searched))
return render(request, "binder_search.html", {'searched': searched, 'binders_searched': binders_searched})
else:
return render(request, "binder_search.html", {})
Then is the csv. This view creates the list of all items in the database. What I am trying to do is get the search result from the above view, and then create the csv file. I would end up with a CSV file that has only the search result in it.
def binders_csv(request):
response = HttpResponse(content_type='text/csv')
response['Content-Disposition'] = 'attachment; filename=binders_result.csv'
# create a csv writer
writer = csv.writer(response)
# designate the model
binders = Binders.objects.all()
# add column at the heading of csv file
writer.writerow(['Item Code', 'Description', 'Item Type', 'Current Step', 'Current Status', 'Last change by'])
# loop thru and output
for binder in binders:
writer.writerow([binder.itemcode, binder.description, binder.itemtype, binder.step, binder.status, binder.user])
return response
I looked around at different solutions, but none actually debugged me. Any idea how to do this?
CodePudding user response:
What am I missing? Can't you just combine the two?
def binder_search(request):
if request.method != "POST":
return render(request, "binder_search.html", {})
# POST
searched = request.POST['searched']
binders_searched = Binders.objects.filter(Q(description__contains=searched) | Q(step__name__contains=searched) | Q(status__name__contains=searched))
# create a csv writer with header writing to response
response = HttpResponse(content_type='text/csv')
response['Content-Disposition'] = 'attachment; filename=binders_result.csv'
writer = csv.writer(response)
writer.writerow(['Item Code', 'Description', 'Item Type', 'Current Step', 'Current Status', 'Last change by'])
# loop thru filtered results and output
for binder in binders_searched:
writer.writerow(
[binder.itemcode, binder.description, binder.itemtype, binder.step, binder.status, binder.user]
)
return response
CodePudding user response:
Here is a solution that works--done with the help of nigel222 and the session framework (request.session). This solution provides the views needed for displaying a search result into a template, and then press a button or link to download that exact result into a CSV format. Therefore, the user can get a search result, and then download the result if he wants to. I have been looking around but couldn't find a similar solution, so I am posting it here for others.
The first view (binder_search) does the search and use request.session to cache the variable "searched".
def binder_search(request):
if request.method == "GET":
searched = request.GET['searched']
# Cache variable "searched" for views.binder_search_csv
request.session['searched'] = searched
# multiple columns
binders_searched = Binders.objects.filter(Q(description__contains=searched) | Q(step__name__contains=searched) | Q(status__name__contains=searched))
return render(request, "binder_search.html", {'searched': searched, 'binders_searched': binders_searched})
else:
return render(request, "binder_search.html", {})
The second view use the cached variable "searched" from the above view and download the search result to a csv file.
def binder_search_csv(request):
if request.method != "GET":
return render(request, "binder_search.html", {})
# Use cached variable from views.binder_search
searched = request.session['searched']
binders_searched = Binders.objects.filter(Q(description__contains=searched) | Q(step__name__contains=searched) | Q(status__name__contains=searched))
# create a csv writer with header writing to response
response = HttpResponse(content_type='text/csv')
response['Content-Disposition'] = 'attachment; filename=binders_result.csv'
writer = csv.writer(response)
writer.writerow(['Item Code', 'Description', 'Item Type', 'Current Step', 'Current Status', 'Last change by'])
# loop thru filtered results and output
for binder in binders_searched:
writer.writerow(
[binder.itemcode, binder.description, binder.itemtype, binder.step, binder.status, binder.user]
)
return response
There might be ways to streamline these two views but as they are right now, they work totally fine.