Reputation:
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
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
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
Reputation: 4687
You could use try/except approach.
try:
some_value = MyModel.objects.filter(...).first()...
except AttributeError:
pass
Upvotes: 0