How to make django querysets with dynamic filters? -
so have website in django storefront , end user has 3 filters use. product type filter (pants, shoes, shirts, etc), delivery filter (yes/no), , location/popularity filter.
currently in views.py have method.
if request.is_ajax(): if request.get.get('filter') == 'shirts': latest_entries = entry.objects.filter(entrytype="shirts") context = {'latest_entries': latest_entries} return render(request, 'storefrontload.html', context) if request.get.get('filter') == 'pants': latest_entries = entry.objects.filter(entrytype="pants") context = {'latest_entries': latest_entries} return render(request, 'storefrontload.html', context) if request.get.get('filter') == 'shoes': latest_entries = entry.objects.filter(entrytype="shoes") context = {'latest_entries': latest_entries} return render(request, 'storefrontload.html', context)
as can see, handles first filter. problem i'm having if select, let's 'pants', filters pants disregards selected in other 2 filters. example, let's select pants, page populates results of filter. if go delivery filter , select "yes", page populates items deliverable, "pants" filter forgotten.
what i'm trying figure how how create queryset in views remembers other 2 querysets (if makes sense).
the way can think of create true/false flags each value in each filter, , add 100 lines of if/then statements checking each flag. there has got better way.
update:
this how passing filter value template.
function filter(type) { $.get("/storefront/?filter="+type, function(data) { var $data = data; $('.grid').children().remove(); $('.grid').append( $data ).masonry( 'appended', $data, true ).masonry( 'layout' ); }); } //product filter $("#shirts").unbind().click(function () { filter("shirts"); return false; }); $("#pants").unbind().click(function () { filter("pants"); return false; }); $("#shoes").unbind().click(function () { filter("shoes"); return false; }); //delivery filter $("#deliveryyes").unbind().click(function () { filter("deliveryyes"); return false; }); $("#deliveryno").unbind().click(function () { filter("deliveryno"); return false; });
in views.py, not work:
entry_types = request.get.getlist('filter') latest_entries = entry.objects.filter(entrytype__in=entry_types)
because need filter entrytype('pants', 'shirts', shoes') , deliveryoption ('deliveryyes', 'deliveryno'). each filter has it's own column in model.
models.py class entry(models.model): headline= models.charfield(max_length=200,) body_text = models.textfield() author=models.foreignkey(settings.auth_user_model, related_name='entryauthors') pub_date=models.datetimefield(auto_now_add=true) zipcode =models.integerfield(null=true, max_length=10) !!! entrytype = models.charfield(null=true, max_length=10) !!! deliveryoption=models.charfield(null=true, max_length=5)
you can pass comma-separated list of filter
values:
/mylist/filter=shirts,pants
and entries using __in
lookup:
entry_types = request.get.get('filter', '').split(',') latest_entries = entry.objects.filter(entrytype__in=entry_types)
or use the getlist()
method of querydict
:
/mylist/filter=shirts&filter=pants
with same orm call:
entry_types = request.get.getlist('filter') latest_entries = entry.objects.filter(entrytype__in=entry_types)
update: pass multiple types view save them in array , use join()
method comma-separated string of them:
var types = []; // shown entry types function filter(type) { // add or remove items grid var index = types.indexof(type); if (index > -1) { types.splice(index, 1); // remove type list } else { types.push(type); // add type filter } $.get("/storefront/?filter="+types.join(","), function(data) { ... } }
update 2: if use 2 fields filter queryset have create 2 separate lists in view:
filters = request.get.getlist('filter') entry_types = [f f in filters if not f.startswith('delivery')] delivery_types = [f f in filters if f.startswith('delivery')] latest_entries = entry.objects.all() if entry_types: latest_entries = latest_entries.filter(entrytype__in=entry_types) if delivery_types: latest_entries = latest_entries.filter(deliverytype__in=delivery_types)
javascript code work without touches.
Comments
Post a Comment