Modal search and display results

Hi,

I am trying to build some search functionality within a modal. When a user clicks a button it will open a modal with a search box. I then want the results of the search to be shown within the same modal?


<div class="modal" id="select2modal">
    <div class="modal-dialog" role="document">
        <div class="modal-content modal-content-demo">
            <div class="modal-header">
                <h6 class="modal-title">Search for product to add</h6><button aria-label="Close" class="close" data-dismiss="modal" type="button"><span aria-hidden="true">&times;</span></button>
            </div>
            <div class="modal-body">
                <h6>product Search</h6>
                <div class="card-body pb-2">
                    <form method=POST action="{% url 'searchproduct' %}">
                        {% csrf_token %}
                        <div class="input-group mb-2">
                                <input type="text" class="form-control border-right-0 pl-3" name="search" placeholder="Enter product Name" value="">
                                <span class="input-group-append">
                                <button class="btn ripple btn-primary" type="submit"><i class="fa fa-search"></i></button>
                            </span>
                        </div>
                    </form>
                </div>
            </div>
            <div class="modal-footer">
                <button class="btn ripple btn-primary" type="button">Add product</button>
                <button class="btn ripple btn-secondary" data-dismiss="modal" type="button">Close</button>
            </div>
        </div>
    </div>
</div>

view


def search_product(request):
    searched = request.POST['searched']
    return {'searched':searched})

The problem is this relies on the page being refreshed that closes the modal, so i have tired to use jquery

        <script type="text/javascript">
            $(document).on('submit','#post-form', function(e){
                e.preventDefault();
                $.ajax({
                    type:'POST',
                    url: '/searchproduct',
                    data:{
                        searched:$('#search').val(),
                        csrfmiddlewaretoken:$('input[name=csrfmiddlewaretoken]').val(),
                    },
                    success: function (){
                    }
                });
            });
        </script>

Which seems is doing a POST and returning 200 but the data returned data isn’t being shown in the modal.


def search_product(request):
    searched = request.POST['searched']
    returned_products = Product.objects.filter(product_name__contains=searched)
    return {'searched':searched,'returned_products':returned_products}

and then within my modal, I am using:

{% for t in returned_products %}
{{t.product_name}}
{% endfor %}

This probably isn’t the right place to ask this, as i think its more jQuery issue, but any ideas where im going wrong?

Thanks

When you’re doing work with jquery, it’s up to you to update the DOM with the data you receive from the server.

Your template is rendered in the server, not in the browser. References to template variables is only valid on the server.

So the root issue here is that you have:

Which receives a response from the server and does nothing with it.

It’s your responsibility to write the JavaScript that takes those results and updates your page with the data received.

Thanks Ken,

So to pass the response back. Do i need to pass httpResposne and then the dict or is
return {'searched':searched,'returned_products':returned_products} ok?

I’ve added

					success: function (data){
						$('jresponse').html(data);
					}

Which i have no idea is right, but when i look within the terminal i get the error:
AttributeError: 'dict' object has no attribute 'headers' which im assuming becuase i not returning a httpresponse ?

Actually, for an AJAX call, you probably want to return a JsonResponse from your view.

def search_product(request):

    searched = request.POST['searched']
    returned_product = Product.objects.filter(product_name__contains=searched)
    data = list(returned_product])
    return JsonResponse(data, safe=False)

I’m getting the following error:
Object of type Product is not JSON serializable

Maybe this approach is not the best way to do things. Im trying to make the UX as slick as i can. So didn’t really want to send the user to a different page.

Is there a better way?

You can prepare html template for the result and then render it with Django via the render_to_string method. This way you can return HTML from your view to your JavaScript code and append it to you page for example.

Or perhaps check out HTMX library, it seems to be quite popular these days in the Djangoverse. They have official example for search - https://htmx.org/examples/active-search/

To address the serialization issue, you could use the “values” clause on your query which makes your queryset return a list-of-dicts instead of the objects. (Therefore removing the need for that following statement - you’re already getting a list.)

Or, as @nemecek_f points out, you can have your view render the html fragment on the server side and just replace an entire div. There are pros and cons to each.

(I know we’ve talked about datatables in the past, if this is a datatable being updated, that raises different issues.)

Thank you both for the replies.

I will take a look at htmx and values

@KenWhitesell This is just a simple query against the list of products in my Products model. I just want to return the name so that I can add it to the user’s account.

How I have the modal working looks nice so it would be good if I can carry on with this approach, but it may be too tough for me being a beginner.

I’ll keep trying though

Thanks

Tom