Home > Enterprise >  Django 3.2 how to fix AttributeError: 'itertools.chain' object has no attribute 'filt
Django 3.2 how to fix AttributeError: 'itertools.chain' object has no attribute 'filt

Time:08-31

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>
  • Related