tags:

views:

129

answers:

3

I'd like to build a function in Django that iterates over a set of objects in a queryset and does something based on the value of an arbitrary attribute. The type of the objects is fixed; let's say they're guaranteed to be from the Comment model, which looks like this:

class Comment(models.Model):
    name = models.CharField(max_length=255)
    text = models.TextField()
    email = models.EmailField()

Sometimes I'll want to do run the function over the names, but other times the emails. I'd like to know how to write and call a function that looks like this:

def do_something(attribute, objects):
    for object in objects:
        # do something with the object based on object.attribute
    return results
+1  A: 

You don't make clear what you want to return from your function, so substitute a suitable return statement. I assume attribute will be set to one of "name", "text" or "email".

def do_something(attribute, objects):
    for o in objects:
        print getattr(o, attribute)
    return something

Update: OK, you've updated the question. Cide's answer makes the most sense now.

Vinay Sajip
+4  A: 
def do_something(attribute, objects):
    results = []
    for object in objects:
        if hasattr(object, attribute):
            results.append(getattr(object, attribute))
    return results

Or, more succinctly,

def do_something(attribute, objects):
    return [getattr(o, attribute) for o in objects if hasattr(o, attribute)]
Nick Lewis
+1: getattr rules.
S.Lott
+4  A: 

If you're only doing stuff with a single attribute, you can use .values_list(), which is more performant since you're not instantiating whole objects, and you're only pulling the specific value you're using from the database.

>>> def do_something(values):
...     for value in values:
...         print value
...     return something
...
>>> emails = Comment.objects.values_list('email', flat=True)
>>> names = Comment.objects.values_list('name', flat=True)
>>> do_something(emails) # Prints all email addresses
>>> do_something(names) # Prints all names
Cide
+1 for a Djangoic solution
Nick Lewis
+1 for Magic Ponies! :)
Frozenskys
Matt Hampel
(sorry I hadn't made that clearer in my example)
Matt Hampel