Django REST Framework

参考記事

Django REST Frameworkは、今までのDjangoにserializer.pyが追加されます。
serializer.pyはJson形式に変換する役割をします。

従来のMVCモデル
- Modelがデータの構造やビジネスロジックを担当
- Viewがデータの表示形式を担当
- Controllerがユーザーの入力とシステムの出力を繋ぐ役割を担当
DRFではこう↓
- Modelはデータの構造やビジネスロジックを担当(変わらず)
- Serializerがデータの表示形式を担当(Viewの役割)
- Viewがユーザーの入力とシステムの出力を繋ぐ役割を担当(Controllerの役割)

Proxy Models(ModelExとして解釈)とは何か?
Proxy modelsは、元のモデルのデータベースの構造を変更することなく、新しいメソッドやデフォルトのマネージャなどのPythonレベルの振る舞いを変更したい場合に使用されます。具体的には、新しいデータベーステーブルを作成せずに、元のモデルのPythonの振る舞いのみを変更します。
なぜProxy Models(ModelEx)が必要か?
Proxy modelsを使用する主な目的は、既存のモデルのデータベース構造を変更することなく、以下のようなことを行いたい場合です:
- 新しいメソッドの追加
- デフォルトのマネージャの変更
- モデルのデフォルトの並び順の変更
例えば、既存のPersonモデルに新しいメソッドを追加したい場合、新しいテーブルを作成することなく、MyPersonというProxy modelsを作成することで、新しいメソッドを追加することができます。
どのようにProxy Models(ModelEx)を宣言するか?
通常のモデルと同じようにProxy modelsを宣言しますが、Metaクラスの中でproxy属性をTrueに設定します。これにより、DjangoはこのモデルがProxy modelsであることを認識します。
あなたが提供してくれた図に基づいて考えると、ModelExがProxy modelsの役割を果たしていると解釈されます。このModelExは、実際のデータベーステーブルとしてのModelの拡張や変更を行うことなく、Pythonの振る舞いのみを変更するために使用されます。

新しいメソッドの追加
イメージとしては、元のモデル側では汎用的なメソッドが定義されており、proxyモデル側では、より限定的なもののみが使用するようなメソッドを定義させる位置付け。

Property属性について
Pythonにおけるpropertyは、メソッドを属性のようにアクセスするためのデコレータです。これにより、オブジェクトの属性を取得、設定、削除する際の振る舞いをカスタマイズすることができます。通常のメソッドを属性のように呼び出すことができるのが特徴です。
基本的な使用方法
class Circle:
def __init__(self, radius):
self._radius = radius
@property
def radius(self):
return self._radius
@property
def diameter(self):
return self._radius * 2
@property
def area(self):
return 3.14 * self._radius * self._radius
circle = Circle(5)
print(circle.radius) # 5
print(circle.diameter) # 10
print(circle.area) # 78.5
上記の例でのポイント:
- radiusは通常の属性のようにアクセスできますが、実際には@propertyデコレータが付与されたメソッドとして定義されています。
- diameterとareaも同様に属性のようにアクセスできますが、これらも@propertyデコレータが付与されたメソッドとして定義されています。
- @propertyを使用することで、計算が必要な属性や内部的には変数の直接アクセスを避けたい場合に役立ちます。
Djangoで使用される理由
- 計算された属性を提供する場合:
モデルのフィールドから導出される値を計算する場面でよく使用されます。例えば、first_nameとlast_nameという2つのフィールドがある場合、フルネームを取得するためのpropertyを作成することができます。
class Person(models.Model):
first_name = models.CharField(max_length=30)
last_name = models.CharField(max_length=30)
@property
def full_name(self):
return f"{self.first_name} {self.last_name}"
-
DBへのクエリを最適化する場合:
いくつかのフィールドを組み合わせて新しい値を生成する場合、その値をDBのクエリとして都度取得するよりも、propertyを使用して動的に計算する方が効率的な場合があります。 -
フィールドの値を変換/整形する場合:
モデルのフィールドの値を特定のフォーマットで取得したい場合、propertyを使用して整形した値を提供することができます。 -
ロジックのカプセル化:
モデルに関連する特定のビジネスロジックをカプセル化し、そのロジックを属性としてアクセスするためにpropertyを使用することができます。 -
互換性の保持:
既存の属性名を変更する場合や、古い属性名を廃止し新しい属性名を導入する場合、既存のコードの動作を保持しつつpropertyを使用して新旧の属性をブリッジすることができます。
これらの理由から、Djangoのモデルにpropertyメソッドを使用することは非常に一般的です。しかし、大量のデータを扱う場面でproperty内でクエリを行う場合、パフォーマンスの問題が発生する可能性もあるため、注意が必要です。
propertyを使用せず通常の関数を使用するケース
- 時間がかかる操作:
データベースへのクエリや、外部APIの呼び出し、複雑な計算など、時間がかかる操作は、メソッドとして明示的に呼び出されるべきです。これは、属性アクセスが即座に値を返すことが期待されるためです。このような時間がかかる操作をpropertyで実装すると、開発者が属性アクセス時に遅延を予期していない場合、パフォーマンスの問題が発生する可能性があります。 - 副作用を伴う操作
- 引数を必要とする操作等