django how to filter data before exporting to csv

Viewed 877

I'm very beginner in django. Now I'm working on my first very simple application. I have a working filter:

def filter_view(request):
    qs = My_Model.objects.all()
    index_contact_contains_query = request.GET.get('index_contact_contains')
    nr_order_contains_query = request.GET.get('nr_order_contains')
    user_contains_query = request.GET.get('user_contains')
    date_min = request.GET.get('date_min')
    date_max = request.GET.get('date_max')

    if is_valid_queryparam(index_contact_contains_query):
        qs = qs.filter(index_contact__icontains = index_contact_contains_query)

    elif is_valid_queryparam(nr_order_contains_query):
        qs = qs.filter(nr_order__icontains = nr_order_contains_query)

    elif is_valid_queryparam(user_contains_query):
        qs = qs.filter(nr_user = user_contains_query)

    if is_valid_queryparam(date_min):
        qs = qs.filter(add_date__gte = date_min)

    if is_valid_queryparam(date_max):
        qs = qs.filter(add_date__lt = date_max)

    if export == 'on':
        ?????????????? - export file 

    context = {
        'queryset':qs
    }
    return render(request,'filter.html',context)

I have also working function for export data to csv file:

def download_csv(request):
    items = My_Model.objects.all()
    response = HttpResponse(content_type='text/csv')
    response['Content-Disposition'] = 'attachment; filename="export.csv"'

    writer = csv.writer(response)
    writer.writerow(['index_contact','nr_order','result','nr_user','tools','add_date'])

    for obj in data:
        writer.writerow([obj.index_contact, obj.nr_order, obj.result, obj.nr_user, obj.tools, obj.add_date])

    return response

My question is... how to connect both functions and export csv file with filtered data.

I also have a request... Please give me a hint as for a beginner

Thanks for any suggestions

2 Answers

You can "inline" the logic from your download_csv view function:

def filter_view(request):
    qs = My_Model.objects.all()
    index_contact_contains_query = request.GET.get('index_contact_contains')
    nr_order_contains_query = request.GET.get('nr_order_contains')
    user_contains_query = request.GET.get('user_contains')
    date_min = request.GET.get('date_min')
    date_max = request.GET.get('date_max')
    export = request.GET.get('export')

    if is_valid_queryparam(index_contact_contains_query):
        qs = qs.filter(index_contact__icontains = index_contact_contains_query)

    elif is_valid_queryparam(nr_order_contains_query):
        qs = qs.filter(nr_order__icontains = nr_order_contains_query)

    elif is_valid_queryparam(user_contains_query):
        qs = qs.filter(nr_user = user_contains_query)

    if is_valid_queryparam(date_min):
        qs = qs.filter(add_date__gte = date_min)

    if is_valid_queryparam(date_max):
        qs = qs.filter(add_date__lt = date_max)

    if export == 'on':
        response = HttpResponse(content_type='text/csv')
        response['Content-Disposition'] = 'attachment; filename="export.csv"'
        writer = csv.writer(response)
        writer.writerow(['index_contact','nr_order','result','nr_user','tools','add_date'])
        for obj in qs:
            writer.writerow([obj.index_contact, obj.nr_order, obj.result, obj.nr_user, obj.tools, obj.add_date])
        return response

    context = {
        'queryset':qs
    }
    return render(request,'filter.html',context)

The missing part here is that your are not preserving Form inputs, that is why you are getting the full items = My_Model.objects.all() downloaded because is_valid_queryparam(index_contact_contains_query) returns false (when you select input values and then click the filter button, the selected input values return to blank).

So in order to preserve Form inputs:

First, modifying Willem answer, pass all request.GET values as context:

def filter_view(request):
    qs = My_Model.objects.all()
    index_contact_contains_query = request.GET.get('index_contact_contains')
    nr_order_contains_query = request.GET.get('nr_order_contains')
    user_contains_query = request.GET.get('user_contains')
    date_min = request.GET.get('date_min')
    date_max = request.GET.get('date_max')
    export = request.GET.get('export')

    if is_valid_queryparam(index_contact_contains_query):
        qs = qs.filter(index_contact__icontains = index_contact_contains_query)

    elif is_valid_queryparam(nr_order_contains_query):
        qs = qs.filter(nr_order__icontains = nr_order_contains_query)

    elif is_valid_queryparam(user_contains_query):
        qs = qs.filter(nr_user = user_contains_query)

    if is_valid_queryparam(date_min):
        qs = qs.filter(add_date__gte = date_min)

    if is_valid_queryparam(date_max):
        qs = qs.filter(add_date__lt = date_max)

    if export == 'on':
        response = HttpResponse(content_type='text/csv')
        response['Content-Disposition'] = 'attachment; filename="export.csv"'
        writer = csv.writer(response)
        writer.writerow(['index_contact','nr_order','result','nr_user','tools','add_date'])
        for obj in qs:
            writer.writerow([obj.index_contact, obj.nr_order, obj.result, obj.nr_user, obj.tools, obj.add_date])
        return response

    context = {
        'queryset':qs
        'values': request.GET  ### this way
    }
    return render(request,'filter.html',context)

Second, modify your filter.html inputs values and options depending on your input types:

For <input type="date"> and <input type="text"> inputs are pretty much straightforward:

<!-- Date input -->
<div class="form-group col-md-2 col-lg-2">
    <label for="publishDateMin">Start date:</label>
    <input type="date" class="form-control" id="publishDateMin" 
    name="date_min" 
    {% if values %}
        value={{values.date_min}}
    {% endif %}>
</div>

<!-- text input -->
<div class="form-group col-md-2 col-lg-2">
    <label for="contactIndex">Contact index:</label>
    <input type="text" class="form-control" id="contactIndex" 
    name="index_contact_contains" 
    {% if values %}
        value={{values.index_contact_contains}}
    {% endif %}>
</div>

For <select name="user_contains" class="form-control"><option value="...">...</option> is a bit different. Let's assume you want to select an user name from a list of user name options:

<!-- Select with options input -->
<div class="form-group col-md-2 col-lg-2">
    <label for="userName">User name:</label>
    <select name="user_contains" class="form-control" id="userName">
<option selected="true" disabled="disabled"> All users </option>
<!-- Looping through queryset to insert options -->
<!-- Here i am assuming you have an user_name column in My_Model -->
{% for s in queryset %}
<option value="{{s.user_name}}" {% if s.user_name == values.user_contains %} selected {% endif %}>
     {{ s.user_name }}
</option>
{% endfor %}
</div>
Related