django-taggit icon indicating copy to clipboard operation
django-taggit copied to clipboard

Further queryset filter parameter for similar_objects method

Open askowronek opened this issue 14 years ago • 14 comments

Hi, as far as I can see the current implementation of TaggableManager::similar_objects lacks the ability to specify further (exclude) filters for the result set. Thanks for investigating this issue.

askowronek avatar Jun 28 '10 13:06 askowronek

That's correct. As the documentation (http://packages.python.org/django-taggit/api.html#similar-objects) says, this method returns a list, not a queryset. I don't think there's anything we can do about this.

alex avatar Jun 28 '10 23:06 alex

I haven't thought of anything, so I'm closing this.

alex avatar Jul 06 '10 03:07 alex

sorry for being late to explain my feature request.

The current implementation requires me to call similar_objects once to get a list of all objects which look the same according to their tags. When I want to apply further filter on that result set, I need to get the IDs of all returned objects first and then do a second query with my filters and the ID list.

I owe you a beer if you could improve the similar_objects method to accept a filter queryset that applies on the queryset to retrieve similar objects ;D.

askowronek avatar Jul 15 '10 07:07 askowronek

I've reopened this to think about it some more.

alex avatar Jul 27 '10 17:07 alex

Bump I really don't want to hurry you since a good job needs the time it requires but I need that feature soon and I believe you can do the job much better here then me.

askowronek avatar Aug 04 '10 08:08 askowronek

I have a branch of Taggit in which I have implemented what seems to be a simple fix for this problem.

Here is how my similar_objects method looks:

def similar_objects(self, num=None, **filters):
    lookup_kwargs = self._lookup_kwargs()
    lookup_keys = sorted(lookup_kwargs)
    qs = self.through.objects.values(*lookup_kwargs.keys())
    qs = qs.annotate(n=models.Count('pk'))
    qs = qs.exclude(**lookup_kwargs)
    subq = self.all()
    qs = qs.filter(tag__in=list(subq))
    qs = qs.order_by('-n')

    if filters is not None:
        qs = qs.filter(**filters)

    if num is not None:
        qs = qs[:num]

    // etc... (the rest is the same)

Now a user can easily specify both a count and any filter methods that they need when doing a similar_objects query.

joshmaker avatar Apr 14 '11 17:04 joshmaker

I'd love to have some extra filtering in place.

Right now I'm writing a FAQ app, and would love to have it return "similar questions". That means creating a "through table" right now, because otherwise other objects will also be returned.

vdboor avatar Jun 04 '14 14:06 vdboor

+1 on this.

melinath avatar Mar 10 '15 17:03 melinath

+1, perhaps order_by would be good too

b-jam avatar Mar 30 '15 21:03 b-jam

+1

Also, the ability to retrieve only objects of a specific given model would be great!

avorio avatar Nov 11 '15 23:11 avorio

+1

legshort avatar Feb 27 '18 10:02 legshort

FYI, this is what I've eventually written back then: https://github.com/django-fluent/django-fluent-utils/blob/master/fluent_utils/softdeps/taggit.py#L73 this code could clearly be optimized, but it could be a good starting point.

vdboor avatar Feb 28 '18 10:02 vdboor

#709 is a dupe of this issue

rtpg avatar Apr 14 '21 04:04 rtpg

looking at this now (after many extra years), I think it might be possible for us to solve this. Django's ORM has made many strides, though the query itself might end up being extra gnarly

rtpg avatar Apr 14 '21 04:04 rtpg