user1541105
user1541105

Reputation:

get attribute from object if object exists

I've been running into this scenario a lot, and I'm wondering if I'm going about it the right way.

I want to get an attribute from an object, but the object might be None.

some_value = myobject.some_value if myobject else None

This works fine if the the variable is short and easy/clean to type.

Where this gets messy is long django queries:

some_value = MyModel.objects.filter(...).first().some_value if MyModel.objects.filter(...).first() else None

I could, theoretically, break this up into multiple lines:

myobject = MyModel.objects.filter(...).first()
some_value = myobject.some_value if myobject else None

but that feels overly cluttered to me.

Is there a cleaner/less verbose way of accomplishing this?

(For reference, there is a lodash function for javascript that does something similar to this)

Upvotes: 6

Views: 5801

Answers (3)

Sardorbek Imomaliev
Sardorbek Imomaliev

Reputation: 15390

You could do getattr and provide default value like this

some_value = getattr(myobject, 'some_value', None)

Also if it is only models related problem you could write custom ModelManager which will be working like this

from django.db import models

class GetValueManager(models.Manager):
    def get_value(self, field_name, filter_kwargs=None):
        filter_kwargs = filter_kwargs or {}
        obj = self.filter(**filter_kwargs).first()
        return getattr(obj, field_name, None)

class MyModel(models.Model):
    field1 = models.CharField()

    objects = GetValueManager()

In code:

some_value = Mymodel.objects.get_value('some_value', filter_kwargs={'field1': 'foo'}

https://docs.djangoproject.com/en/1.9/topics/db/managers/#adding-extra-manager-methods

Upvotes: 6

Seb D.
Seb D.

Reputation: 5195

You could use getattr:

some_value = getattr(MyModel.objects.filter(...).first(), 'some_value', None)

But IMHO breaking it into two lines is much cleaner and explicit on your intention!

Upvotes: 5

xiº
xiº

Reputation: 4687

You could use try/except approach.

try:
    some_value = MyModel.objects.filter(...).first()...
except AttributeError:
   pass

Upvotes: 0

Related Questions