Matt Hampel
Matt Hampel

Reputation: 5237

Passing a Django model attribute name to a function

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

Upvotes: 1

Views: 1393

Answers (3)

André Eriksson
André Eriksson

Reputation: 4360

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

Upvotes: 4

Vinay Sajip
Vinay Sajip

Reputation: 99355

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.

Upvotes: 1

Nick Lewis
Nick Lewis

Reputation: 4230

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)]

Upvotes: 4

Related Questions