Ryan Saxe
Ryan Saxe

Reputation: 17849

Django method returning

With a method to get all related connections, is it better to simply return a queryset, or iterate through the queryset to return a list of IDs?

example code:

class Foo(models.Model):
    bar = models.ForeignKey(Bar, related_name="foos")

class Bar(models.Model):
    is_active = models.BooleanField(default=True)
    
    def get_foos(self):
        #this is the method to focus on for the question

to return a queryset all that would need to be in get_foos is the following:

return self.foos.all()

but to get a list of ids, it would have to look as such:

foos = self.foos.all()
ids = []
for foo in foos:
    ids.append(foo.pk)
return ids

I was looking through an API, and they used the latter, but I don't really understand why you would ever actually do that if you could just do a one-liner like the former! Can someone please explain the benefits of these methods and if there are specific cases in which one is better than the other?

Upvotes: 1

Views: 69

Answers (3)

salezica
salezica

Reputation: 76949

I don't think this is a better vs worse scenario. The ID list can also be generated with a one-liner:

list(self.foos.values_list('pk', flat=True))

It's sometimes good practice for a function to return the minimal or least powerful representation of the data requested. Maybe you don't want callers to have access to the queryset object.

Maybe those IDs are going to the template rendering engine, and you'd rather not have templates with write access to querysets, for example.

Upvotes: -1

bruno desthuilliers
bruno desthuilliers

Reputation: 77912

If you really saw something like your second snippet in some published app, then you can send them a patch (and probably more than one, since chances are you'll find a lot of bad code in this app). Point is : there's a lot of very poorly written Django apps around. As Niekas posted, you can get the same result with whay better performances in a no-brainer one-liner.

Now wrt/ why return a list of pks instead of a full queryset, well, sometimes that's really just what you need, and sometimes that's just silly - depends on the context, really.

Upvotes: 1

niekas
niekas

Reputation: 9097

You can get Foo ids in one line:

ids = self.foos.values_list('pk', flat=True)

Using id list is more efficient if used in other expressions, e.g.:

my_query.filter(foo__pk__in=ids)

Upvotes: 4

Related Questions