[Fixed]-Django filter object with list of values

1👍

How about use request.GET.getlist('tags[]', '') ?

Result Before Search

before

Result After Search by ajax

after


This example below is how to implement it.

Example:

1. yourapp/models.py

from django.db import models

class Foo(models.Model):
    name = models.CharField(max_length=200)

    def __str__(self):
        return self.name


class Ref(models.Model):
    foo = models.ManyToManyField(Foo, related_name='ref_foo')
    other = models.CharField(max_length=200)

    def __str__(self):
        return self.other

2. yourapp/views.py

from django.shortcuts import render
from foo.models import (Foo, Ref)

def fooview(request):
    foos = Foo.objects.all()
    refs = Ref.objects.all()
    return render(
      request, 'foo.html', 
      {'types_list': foos, 'refs': refs}
    )

def search(request):
    if request.is_ajax():
        tags = request.GET.getlist('tags[]', '')
        #print(tags)
        if tags != '':
            results = Ref.objects.filter(foo__name__in=tags).distinct()
            return render(
              request, 'search.html', 
              {'results': results, 'tags': tags}
            )
    return render(request, 'search.html', {})

3. yourapp/urls.py

from django.conf.urls import url
from yourapp.views import (fooview, search)

urlpatterns = [
    url(r'^$', fooview, name='foo'),
    url(r'^search/$', search, name='search')
]

3. templates/foo.html

<!DOCTYPE html>
<html>
<head>
  <script src="https://code.jquery.com/jquery-3.1.1.min.js"></script>
</head>

<body>
<div class="original-data">
 Original Data:<br />
 {% for ref in refs %}
   <li>{{ ref }} - {% for foo in ref.foo.all %}{{ foo }}, {% endfor %}</li>
 {% endfor %}
</div>
<hr />

<div class="main-search">
  <div class="SearchWithTags">
    <select name="tags" id="TagDropDown">
      <option>Choice categories...</option>
      {% for k in types_list %}
        <option value="{{ k.name }}">{{ k.name }}</option>
      {% endfor %}
    </select>
    <div class="PlaceForTags">
      <div id="PlaceForTagsId" class="Tags">
      </div>
    </div>
  </div>
  <button id="SendTagArray" class="search">Search...</button>
</div><!-- end /.main-search -->

<div class="main-results">
</div>

<script>
  values = [];
  $(function() {
    $('#TagDropDown').change(function() {
        var val = $('#TagDropDown option:selected').text();
      // check if has duplicate values
      if (values.includes(val) == false){
        values.push(val);
        $('#PlaceForTagsId').append("<div class='tagex'>" +$('#TagDropDown option:selected').text()+"</div>");
      }
    });
    $("#SendTagArray").click(function(){
      console.log(values);
      $.ajax({
        type: 'GET',
        url: '{% url "search" %}',
        data: {
          'csrfmiddlewaretoken': '{{ csrf_token }}', 
          'tags': values
        },
        success: function(data) {
           $('.main-results').html(data);
        },
        error: function(data) {
           console.log(data);
        }
      });
    });
  });
</script>
</body>
</html>

4. templates/search.html

<div class="results">
  Result of {{ tags }}:
  <hr />

  {% for result in results %}
    <li>{{ result }}</li>
  {% endfor %}
</div>

Leave a comment