Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Check if a OneToOne relation exists in Django

Now I'm using django 1.6

I have two models relates with a OneToOneField.

class A(models.Model):     pass  class B(models.Model):     ref_a = models.OneToOneField(related_name='ref_b', null=True) 

First see my code that points out the problem:

a1 = A.objects.create() a2 = A.objects.create() b1 = B.objects.create() b2 = B.objects.create(ref_a=a2)  # then I call: print(a1.ref_b)  # DoesNotExist Exception raised print(a2.ref_b)  # returns b2 print(b1.ref_a)  # returns None print(b2.ref_a)  # returns a2 

Now the problem is, if I want to check a A object, to judge whether it exists a B objects referencing it. How can I do?

The valid way I tried is only to try and catch an exception, but is there any other prettier way?


My effort:

1 - The below code works, but is too ugly!

b = None try:     b = a.ref_b except:     pass 

2 - I also tried to check the attributes in a, but not working:

b = a.ref_b if hasattr(a, 'ref_b') else None 

Do you meet the same problem, friends? Please point me a way, thank you!

like image 491
Alfred Huang Avatar asked Sep 20 '14 03:09

Alfred Huang


People also ask

What is Onetoone field in Django?

This field can be useful as a primary key of an object if that object extends another object in some way. For example – a model Car has one-to-one relationship with a model Vehicle, i.e. a car is a vehicle. One-to-one relations are defined using OneToOneField field of django.

How do I get OneToOneField in Django?

Accessing OneToOneField Model fields in Django TemplatesGet all the objects of the model 'Contact' in your views.py file. And pass this to the template. Now, go to your HTML template and add this code.

What is relation in Django?

Any association between two entity types is called a “relationship”. A relationship works between two relational database tables where one table has the foreign key of the other table's primary key. Relationships allow us to split and store data in different tables.


2 Answers

So you have a least two ways of checking that. First is to create try/catch block to get attribute, second is to use hasattr.

class A(models.Model):    def get_B(self):        try:           return self.b        except:           return None  class B(models.Model):    ref_a = models.OneToOneField(related_name='ref_b', null=True) 

Please try to avoid bare except: clauses. It can hide some problems.

The second way is:

class A(models.Model):     def get_B(self):        if(hasattr(self, 'b')):            return self.b        return None  class B(models.Model):     ref_a = models.OneToOneField(related_name='ref_b', null=True) 

In both cases you can use it without any exceptions:

a1 = A.objects.create() a2 = A.objects.create() b1 = B.objects.create() b2 = B.objects.create(ref_a=a2)  # then I call: print(a1.get_b)  # No exception raised print(a2.get_b)  # returns b2 print(b1.a)  # returns None print(b2.a)  # returns a2 

There is no other way, as throwing the exception is default behaviour from Django One to One relationships.

And this is the example of handling it from official documentation.

>>> from django.core.exceptions import ObjectDoesNotExist >>> try: >>>     p2.restaurant >>> except ObjectDoesNotExist: >>>     print("There is no restaurant here.") There is no restaurant here. 
like image 79
Mr.Coffee Avatar answered Oct 17 '22 20:10

Mr.Coffee


Individual model classes provide a more specific exception called DoesNotExist that extends ObjectDoesNotExist. My preference is to write it this way:

b = None try:     b = a.ref_b except B.DoesNotExist:     pass 
like image 23
dhackner Avatar answered Oct 17 '22 21:10

dhackner