RealEstateAgent is a model and doing RealEstateAgent.objects.filter(name = 'better homes') returns 5 objects.
I would like to use RealEstateAgent.objects.get(name='better homes') to catch the MultipleObjectsReturned exception.
Im trying this but the exception is not getting caught.
from django.core.exceptions import MultipleObjectsReturned
try:
RealEstateAgent.objects.get(name='bh')
except MultipleObjectsReturned, e:
print ''
this is the traceback:
DoesNotExist Traceback (most recent call last)
<ipython-input-49-9458986408df> in <module>()
1 try:
----> 2 RealEstateAgent.objects.get(name='better homes')
3 except MultipleObjectsReturned, e:
4 print ''
5
/home/dubizzle/webapps/django/src/django/django/db/models/manager.pyc in get(self, *args, **kwargs)
130
131 def get(self, *args, **kwargs):
--> 132 return self.get_query_set().get(*args, **kwargs)
133
134 def get_or_create(self, **kwargs):
/home/dubizzle/webapps/django/src/django/django/db/models/query.pyc in get(self, *args, **kwargs)
347 if not num:
348 raise self.model.DoesNotExist("%s matching query does not exist."
--> 349 % self.model._meta.object_name)
350 raise self.model.MultipleObjectsReturned("get() returned more than one %s -- it returned %s! Lookup parameters were %s"
351 % (self.model._meta.object_name, num, kwargs))
DoesNotExist: RealEstateAgent matching query does not exist.
It seems like there are some deeper issues with your code, but without more information those are difficult to debug. As far as your original question however, your line:
except MultipleObjectsReturned, e:
Will only catch exceptions of the type MultipleObjectsReturned. If you look at your traceback however, you see the actual exception being raised is a DoesNotExist exception.
If you change your except line (above) to :
except DoesNotExist, e:
It should properly catch that exception.
As for why the exception is raised in the first place, I'm willing to guess that you just don't have that object in your database. Are you inserting it anywhere? If you're looking for a backend that will automatically construct an entry for you when you try to access it, look into mongodb. Your current SQL database however, will error if you try to access an object that does not exist.
Based on what you said in the comments, it seems you misunderstand exactly what exception handling is. Specifically when you catch an exception, you are saying "This is an error that I am aware may happen and I have a contingency case for it".
The reason you might get a MultipleObjectsReturned exception is because the get method you used above is specifically for returning a single result. If you want to query for multiple entries you use a filter instead:
my_objects = RealEstateAgent.objects.filter(name='bh')
which will return a QuerySet filled with entries that match your query.
With that said, since a DoesNotExist exception is being raised, your assumption that there are five objects matching the query in your database appears to be incorrect.
To address your use case, you could pretty easily implement something along these lines:
my_objects = RealEstateAgent.objects.filter(name='bh')
if len(my_objects) > 1:
# Ask user to pick one
Related
I have a python script and a database. They are connected. The python script raises some errors when the inputs are wrong. For example, one of the functions is to count classes. If there are less than 2 classes, an OneClassError is raised and the program is killed. There are other customized errors like OneClassError.
There is a column in my database table called error_code. It should update according to the specific error I get. For instance, it should be 401 if it's OneClassError; it should be 402 if it's TestClassMsg. (I make up the error names here just for easier illustration.)
For now, I only know how to update that column by a single value. I wonder how to automate the process that there are 401 and 402 where I don't need to specify 401 or 402 - the error_code identifies the error and knows the code for it.
# here is my simplified example:
def count_class_sim(inp_data):
"""
:param inp_data: the path of the input data
:return: pass or fail
"""
unique_cc, count_cc = np.unique(inp_data[inp_data != 0], return_counts=True)
if len(unique_cc) < 2:
raise OneClassError()
else:
raise TestClassMsg()
data1 = np.array([0,0,1,2,3,3,4,5,5,5])
count_class_sim(data1) # ---- TestClassMsg: TestingTesting
data2 = np.array([0,0,1])
count_class_sim(data2) # ---- OneClassError: Data has only 1 non-zero class - rejected.
Here is my database connection code. Note that I only know how to give a single value to error_code. I want a sophisticated way to do that. Can anyone show me how to modify the "set error_code = "command?
try:
count_class_sim(data2)
except:
cur.execute("""update lc_2020 set error_code = 401
where quad_id = '010059' """)
conn.commit()
Since you have custom error, you can mention your error code in custom error class itself.
Example:
class OneClassError(Exception):
code = 401
def __init__(self):
pass
#remaining logic
try:
#code that may cause Exception OneClassError
except OneClassError as e:
print(e.code)
I hope I Understand your query and answered right, If any questions ask in comment section.
Django's docs say this about transaction.atomic() and exceptions:
https://docs.djangoproject.com/en/1.10/topics/db/transactions/#django.db.transaction.atomic
Avoid catching exceptions inside atomic!
...
The correct way to catch database errors is around an atomic block as shown above. If necessary, add an extra atomic block for this purpose. This pattern has another advantage: it delimits explicitly which operations will be rolled back if an exception occurs.
...
What does "If necessary, add an extra atomic block for this purpose." look like? Can I do this or does this cause "unexpected behavior"?
valid = True
errors = []
objects = MyModel.objects.all()
try:
with transaction.atomic():
for obj in objects:
try:
# Update and save obj here...
except:
errors.append("obj {} had errors".format(obj.pk))
valid = False
if not valid:
raise Exception('batch update failed.')
except Exception as ex:
# Handle it..
Do they mean to write it like this? If so, why is this different?
valid = True
errors = []
objects = MyModel.objects.all()
try:
with transaction.atomic():
for obj in objects:
try:
with transaction.atomic(): # Here's my 'extra atomic block'
# Update and save obj here...
except:
errors.append("obj {} had errors".format(obj.pk))
valid = False
if not valid:
raise Exception('batch update failed.')
except Exception as ex:
# Handle it..
Django triggers rolback only when transaction block catches DatabaseError (or its subclass), So you shouldn't catch it before it. If you add second transaction block (your 2nd example), error is caught, transaction is marked to rollbacked, and then you can do whatever you want.
I think that you should be good it yo re-raise exactly the same error, but this is just a guess.
I was wondering if its possible to write a handling exceptions like with 2 or more except with different task to do.
I'm using Django==1.6.1 and Python 2.7
try:
foo_instance = foo.objects.get(field_name='unknown')
except foo.DoesNotExist:
new_rec = foo.objects.create(field_name='unknown')
new_rec.save()
foo_instance = foo.objects.get(field_name='unknown')
except foo.MultipleObjectsReturned:
foo_list = foo.objects.filter(field_name='unknown')
for record in foo_list[1:]:
print 'Deleting foo id: ', record.id
record.delete()
foo_instance = foo.objects.get(field_name='unknown')
You could use multiple try: except: but in your current scenario Why don't you use get_or_create ?
try: expect: contain all errors on 'Exception'. for this syntax is all
except Exception as e:
get_or_create(defaults=None, **kwargs)
A convenience method for looking up an object with the given kwargs
(may be empty if your model has defaults for all fields), creating one
if necessary.
Returns a tuple of (object, created), where object is the retrieved or
created object and created is a boolean specifying whether a new
object was created.
This reduces your above code to -
obj, created = foo.objects.get_or_create(field_name='unknown')
if created:
obj.save()
I think get_or_create raises IntegrityError or MultipleObjectsReturned, to handle those simply wrap it in a try:
try:
obj, created = foo.objects.get_or_create(field_name='unknown')
if created:
obj.save()
except IntegrityError:
#do something
except MultipleObjectsReturned:
#do something else
except Exception as e:
raise e
I have a function with a try catch block where I have:
def testfunction():
try:
good = myfunction()
return good
except ExceptionOne:
error="Error ExceptionOne".
return error
except ExceptionTwo:
error="Error ExceptionTwo".
return error
except ExceptionThree:
error="Error ExceptionThree".
return error
Is there a way such that I could structure this in such a way where have a single return statement for all the exceptions?
What about something like:
def testfunction():
try:
good = myfunction() # or `return myfunction()` if the case is actually this simple
except (ExceptionOne, ExceptionTwo, ExceptionThree) as err:
error = 'Error %s' % err.__class__.__name__
return error
return good
Of course, I'm not exactly sure what the purpose of this is. Why not just let the exception propogate and handle it higher up? As it is, you need logic to check the return value to see if it's good or not anyway, I think it would be cleaner if that logic was bound up in exception handling rather than in type checking or string value checking ...
I've create little class for parsing websites.
There's URLError exception:
def visit(self, url, referer=None, data=None):
(...)
# Return BeautifulSoup instance.
try:
return BeautifulSoup(self.opener.open(self.request))
# URLError.
except urllib.error.URLError as error:
return error
Everything works okay. But I'm in need to create a wrapper of this function.
def get_links(self, *args, **kwargs):
# Get links with BeautifulSoup.
self.links = self.visit(*args, **kwargs).find_all('a')
Get_links function also works well until there is URLError (403, 404, whatever...). How can I solve this problem? Is there something as inheritance exceptions?
Your visit() function catches exception and returns you a URLError object, on which you're calling find_all(), which it doesn't have.
Something in lines of:
self.links = self.visit(*args, **kwargs)
if not isinstance(self.links, urllib.error.URLError):
self.links = self.links.find_all('a')
else:
# Do something with an HTTP Error
Should give you an idea of a flow. You can't catch that exception in your outer get_links() because it's already caught by visit() and is simply returned.
If you want to catch it in get_links(), change
return error
to
raise error
in your visit() method, although then you'll be throwing the exception you just caught again, I'm not sure whether this is the behavior you want.