Reputation: 31189
I have two expressions. I need to try one expression, if it is raise an exception try another, but if the second raises an exception too - to raise the exception.
I tried this, but it is looks ugly and I am not sure it is the best way to solve this issue:
try:
image = self.images.order_by(func.random()).limit(1)
except:
try:
image = self.images.order_by(func.rand()).limit(1)
except ProgrammingError:
raise ProgrammingError(
'The database engine must be PostgtreSQL or MySQL')
How do you do it?
Upvotes: 8
Views: 15215
Reputation: 184270
Use a loop:
for methname in ("random", "rand"):
try:
image = self.images.order_by(getattr(func, methname)()).limit(1)
break
except ProgrammingError:
continue
else:
raise ProgrammingError("The database engine must be PostgtreSQL or MySQL")
The loop's else
clause is executed only if the loop terminates normally (i.e., without a break
) which is why we break
after doing the image
assignment. If you consider this too tricksy, because the else
clause is so infrequently used with for
, then this would also work:
image = None
for methname in ("random", "rand"):
try:
image = self.images.order_by(getattr(func, methname)()).limit(1)
except ProgrammingError:
continue
if not image:
raise ProgrammingError("The database engine must be PostgtreSQL or MySQL")
Upvotes: 7
Reputation: 34116
Making a separate function is very helpful.
def get_random_image(self):
for rand in func.random, func.rand:
try:
return self.images.order_by(rand()).limit(1)
except ProgrammingError:
pass
raise ProgrammingError('This database engine is not supported')
Upvotes: 5
Reputation: 1123420
In this particular case, I'd actually try and detect the database before selecting the function. Can you reach the database connection from your code? If so, just switch on the drivername:
random = None
if drivername == 'postgres':
random = func.random
elif drivername == 'mysql':
random = func.rand
else:
raise ValueError('This module requires that you use PostgreSQL or MySQL')
Then, when selecting images, use the random
value:
image = self.images.order_by(random()).limit(1)
Upvotes: 3
Reputation: 15367
If you want to check if rand or random is a function of a class, you also could use
if 'rand' in dir(some object of a class)
Upvotes: 0
Reputation: 15367
Actually it MIGHT be a design flaw. Raising exceptions is to act on an event that should normally not occur. If you want to do something functionally into an except (except for handling the exception), than it looks like the first statement that you want to try is not a statement that should get an exception at all.
So instead of:
try:
do statement 1
except ...
try:
do statement 2
except:
think about :
if (statement_1 result == ...)
try:
do statement 2
except:
Upvotes: 1