Django 3.2 how to fix AttributeError: 'itertools.chain' object has no attribute 'filter' error?

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.

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

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>
Back to Top