I have 3 querysets that I need to merge and use filter
method when the user selects a checkbox. Ajax works fine but I am struggling with displaying filtered data because I am getting this error:
AttributeError: 'itertools.chain' object has no attribute 'filter'
When I am trying to iterate over 1 model like this favourite_list=Product.objects.all()
everything works fine but in my case, I need to filter data from 3 different models.
I tried to use list(chain(fa, fv, fp))
but it gives me list object has no attribute filter
error.
def filter_favourites(request):
favourite_articles = request.GET.getlist('favourite_articles[]')
favourite_video = request.GET.getlist('favourite_video[]')
favourite_product = request.GET.getlist('favourite_product[]')
fa = request.user.favourite_article.all().distinct() #list of favourites items from Article model
fv = request.user.favourite_video.all().distinct() #list of favourites items from Video model
fp = request.user.favourite_product.all().distinct() #list of favourites items from Product model
favourite_list = chain(fa, fv, fp)
if len(favourite_articles) > 0:
favourite_list = favourite_list.filter(title__in=favourite_articles).distinct()
if len(favourite_video) > 0:
favourite_list = favourite_list.filter(title__in=favourite_video).distinct()
if len(favourite_product) > 0:
favourite_list = favourite_list.filter(title__in=favourite_product).distinct()
context = {
'combined_queryset': favourite_list,
}
ajax_template = render_to_string('user/user_favourites_ajax.html', context)
return JsonResponse({'data': ajax_template})
My question is how can I fix this error? How should I merge fa, fv, pd
so they behave like normal querysets and I can use filter
method on them.
CodePudding user response:
filter method is for objects with type of QuerySet, so you can't use it on list and chain.
instead you can group the favourites after filtering
def filter_favourites(request):
favourite_articles = request.GET.getlist('favourite_articles[]')
favourite_video = request.GET.getlist('favourite_video[]')
favourite_product = request.GET.getlist('favourite_product[]')
fa = request.user.favourite_article.all().distinct() #list of favourites items from Article model
fv = request.user.favourite_video.all().distinct() #list of favourites items from Video model
fp = request.user.favourite_product.all().distinct() #list of favourites items from Product model
if len(favourite_articles) > 0:
fa = fa.filter(title__in=favourite_articles)
if len(favourite_video) > 0:
fv = fv.filter(title__in=favourite_video)
if len(favourite_product) > 0:
fp = fp.filter(title__in=favourite_product)
favourite_list = chain(fa, fv, fp)
context = {
'combined_queryset': favourite_list,
}
ajax_template = render_to_string('user/user_favourites_ajax.html', context)
return JsonResponse({'data': ajax_template})
and no need to use distinct again after conditions, it has done once before
CodePudding user response:
Well, seems that QuerySet.union()
is what you're looking for.
favourite_list = fa.union(fv, fp)
As for your initial question, neither list
nor intertools.chain
(which is the type returned by itertools.chain()
) types have a filter()
method, hence the errors.
>>> chain(["a"], ["b"])
<itertools.chain object at 0x7fd3f0a86580>