KakBeOlolo
KakBeOlolo

Reputation: 5

Ajax live search in header on wagtail/Django

I recently just started learning Python, Wagtail and Django. There was a need to create a live search in the header of the site, but I just can’t get it to work correctly; as a result of the search, the entire page with search results is loaded.

Here's the code I put a lot of effort into:

in header.html:

<div class="block_search">
<input type="text" class="search_input searchbox"  id="search_header" value="" placeholder="Поиск товара..." name="q"  >
{% include "tags/header_search.html" %}
</div>
        

header_search.html:

{% load static wagtailcore_tags header_tags %}

<div id="search_box-result">
    {% get_header_search as search_result%}
    {% for result in search_result %}
    {{result.title}}
    {% endfor %}
</div>

Jquery:

<script>
        
                $(document).ready(function () {
                    $('#search_header').on('input',function(e){
                        var search_result = $("#search_header").val();
                        $.ajax({
                            type: 'GET',
                            cache: true,
                            url: '',
                            data: {"search": search_result},
                            success: function (response) {
                                $("#search_box-result").replaceWith(response)
                            }
                        });
                    });
                    
                    
                });
</script>

header_tags.py:

@register.simple_tag(takes_context=True)
def get_header_search(context):
    request = context['request']
    if request.method == 'GET':
        search_query = request.GET.get("search", None)
        print(search_query)
        if search_query:
            search_results = Page.objects.live().search(search_query)
        else:
            search_results = Page.objects.none()
        return search_results

`In browser: enter image description here

enter image description here

Upvotes: 0

Views: 124

Answers (2)

KakBeOlolo
KakBeOlolo

Reputation: 5

my solution to the problem

Wagtail has ajax_template, it specifies a template that will respond to any Ajax request, but it specifies one template. I overridden the function for getting a template and, depending on the get request, displays the desired template.

I don't know how correct this is, but it works without problems.

class CategoryPage(Page):
parent_page_types = ['catalog.CatalogPage','category.CategoryPage']
subpage_types = ['category.CategoryPage','product.ProductPage']
def get_template(self, request, *args, **kwargs):
    if request.headers.get("x-requested-with") == "XMLHttpRequest":
        if request.GET.get("search", None) != None:
            self.ajax_template = 'tags/header_search.html'
        elif request.GET.getlist('platforms_ids[]', None) != None or request.GET.getlist('types_ids[]', None) != None or request.GET.get('page[]', 1) != None:
            self.ajax_template = "tags/category_filtered_products_for_ajax.html"
        return self.ajax_template or self.template
    else:
        return self.template

Upvotes: 0

matt
matt

Reputation: 52

I think you need a way to identify where is an ajax call or a user call from a browser. I want that too. Considering what is the difference between ajax and user browser request I found this link When I can differentiate between those call I made this code:

def is_ajax(request):
  if(request.headers.get('SEC_FETCH_SITE') == "same-origin"):
    return True
  return False    

class Model(Page):
  description = models.CharField(max_length=511)
  def get_template(self, request):
    if is_ajax(request):
      return "base/model_ajax.html"
    return "base/model_page.html"

When you look up your get_header_search tag, you can differentiate if it's ajax or not. Maybe when it's ajax, you can use another template or a JsonResponse, and when isn't, you can load a different template.

When you ask by ajax, you need an URL, that url in wagtail could be a Wagtail API syntax or just a static url that could be rendered with the django context processor. In my case, it was for a static URL rendered inside the template, when I click it, I make an ajax call to a document specifically for a template, and when it wasn't . I just put a normal template.

I hope it helps.

Upvotes: 0

Related Questions