web-dev-qa-db-ja.com

OneToOneリレーションがDjango

今私はDjango 1.6を使用しています

OneToOneFieldに関連する2つのモデルがあります。

class A(models.Model):
    pass

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

まず、問題を指摘している私のコードを見てください。

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

ここで問題となるのは、Aオブジェクトをチェックしたい場合、それを参照するBオブジェクトが存在するかどうかを判断することです。どのようにできるのか?

私が試した有効な方法は、例外をキャッチすることだけですが、他にもっときれいな方法はありますか?


私の努力:

1-以下のコードは機能しますが、醜いです!

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

2-aの属性も確認しようとしましたが、機能しませんでした。

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

友達、同じ問題に遭遇しますか?道を教えてください、ありがとう!

15
Alfred Huang

したがって、それを確認する方法は少なくとも2つあります。 1つは属性を取得するためのtry/catchブロックを作成することであり、2つ目は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)

裸のexcept:句は避けてください。それはいくつかを隠すことができます 問題

2番目の方法は次のとおりです。

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)

どちらの場合も、例外なく使用できます。

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

例外のスローはDjango 1対1の関係 からのデフォルトの動作であるため、他の方法はありません。

そして、これは公式ドキュメントからそれを処理する例です。

>>> from Django.core.exceptions import ObjectDoesNotExist
>>> try:
>>>     p2.restaurant
>>> except ObjectDoesNotExist:
>>>     print("There is no restaurant here.")
There is no restaurant here.
21
Mr.Coffee

個々のモデルクラスは、ObjectDoesNotExistを拡張するDoesNotExistと呼ばれるより具体的な例外を提供します。私の好みは次のように書くことです:

b = None
try:
    b = a.ref_b
except B.DoesNotExist:
    pass
7
dhackner

hasattrはDjango1.11で正常に動作します!短いバージョンにはgetattrを使用できます。

getattr(self, 'field', default)

あなたの場合

b = getattr(a, 'ref_b', None)

https://docs.python.org/3.6/library/functions.html#getattr

1
Heretron