Rodwan Bakkar
Rodwan Bakkar

Reputation: 484

filtering a queryset, applying more than one filter

My models are:

models.User:
       id = pk
       username = text

    models.Offer
       id = pk           
       description = text
       publicationDate = Date
       user = Fk(User)

    my serializer is:

    class UserOfferSerializer(ModelSerializer):
        offers = OfferSerializerAll(many=True, read_only=True)
        class Meta:
            model = User
            fields = ('id', 'username', 'offers')

I am trying to apply more than one filter on the queryset:

users = users.filter(offers__publicationDate__range=[startdate, enddate]). prefetch_related(Prefetch('offers', queryset=Offer.objects.filter(
publicationDate__range=[startdate, enddate]))).distinct()

then

users = users.filter(offers__description__icontains=sometext).prefetch_related(Prefetch('offers', queryset=Offer.objects.filter(description__icontains=sometext))).distinct()

First one works fine and the other one throws the following exception:

ValueError: 'offers' lookup was already seen with a different queryset. You may need to adjust the ordering of your lookups.

Update:

My current code is:

    if (offerBeginDate != None and offerEndDate != None):
        b = offerBeginDate.split('-')
        e = offerEndDate.split('-')

        startdate = datetime.date(int(b[0]), int(b[1]), int(b[2]))
        enddate = datetime.date(int(e[0]), int(e[1]), int(e[2]))

        users = users.filter(offers__publicationDate__range=[startdate, enddate])
        offers = offers.filter(publicationDate__range=[startdate, enddate])

    if (descriptionText != None):

        users = users.filter(offers__functionDescription__icontains=descriptionText.strip())
        offers = offers.filter(functionDescription__icontains=descriptionText.strip())


    users = users.prefetch_related('offers', Prefetch(queryset=offers))

Any help? Thank you all :)))

Upvotes: 1

Views: 858

Answers (1)

neverwalkaloner
neverwalkaloner

Reputation: 47354

You can use to_attr argument of Prefetch object to prefetch additional queryset:

users = users.filter(offers__description__icontains=sometext).prefetch_related(
        Prefetch('offers', queryset=Offer.objects.filter(
publicationDate__range=[startdate, enddate]), to_attr='date_offers'), 
        Prefetch('offers', queryset=Offer.objects.filter(description__icontains=sometext), to_attr='description_offers')).distinct()

UPD

If you need dynamically add filters to prefetched queryset you can define it separately like this:

if some_case:
    users = users.filter(offers__description__icontains=sometext)
    offers=Offer.objects.filter(description__icontains=sometext)
if some_case_2:
    users = users.filter(**conditions)
    offers = offers.filter(**conditions)

users = users.prefetch_related(Prefetch('offers', queryset=offers))

Now each user in users queryset will have two attributes: user.date_offers and user.description_offers.

Upvotes: 2

Related Questions