web-dev-qa-db-ja.com

Django Rest Frameworkを使用して関連モデルフィールドを含めるにはどうすればよいですか?

次のモデルがあるとしましょう:

class Classroom(models.Model):
    room_number = [....]

class Teacher(models.Model):
    name = [...]
    tenure = [...]
    classroom = models.ForeignKey(Classroom)

ManyRelatedPrimaryKeyField関数ごとにこのような結果を取得する代わりに、

{
    "room_number": "42", 
    "teachers": [
        27, 
        24, 
        7
    ]
},

次のような完全な関連モデル表現を含むものを返します:

{
    "room_number": "42", 
    "teachers": [
        {
           'id':'27,
           'name':'John',
           'tenure':True
        }, 
        {
           'id':'24,
           'name':'Sally',
           'tenure':False
        }, 
    ]
},

これは可能ですか?もしそうなら、どのように?そして、これは悪い考えですか?

132
Chaz

最も簡単な方法は、 深度引数 を使用することです

class ClassroomSerializer(serializers.ModelSerializer):
    class Meta:
        model = Classroom
        depth = 1

ただし、これには前方関係の関係のみが含まれます。この場合、教師フィールドは逆関係であるため、必要なものではありません。

より複雑な要件がある場合(たとえば、逆の関係を含める、一部のフィールドをネストし、他のフィールドはネストしない、またはフィールドの特定のサブセットのみをネストする)、 nesterizers など、次のことができます。

class TeacherSerializer(serializers.ModelSerializer):
    class Meta:
        model = Teacher
        fields = ('id', 'name', 'tenure')

class ClassroomSerializer(serializers.ModelSerializer):
    teachers = TeacherSerializer(source='teacher_set')

    class Meta:
        model = Classroom

シリアライザーフィールドでsource引数を使用して、フィールドのソースとして使用する属性を指定することに注意してください。 sourceモデルで related_name オプションを使用して、代わりにteachers属性が存在することを確認することで、Teacher引数を削除できます。 classroom = models.ForeignKey(Classroom, related_name='teachers')

覚えておくべきことの1つは、ネストされたシリアライザーは現在、書き込み操作をサポートしていないことです。書き込み可能な表現の場合、pkやハイパーリンクなどの通常のフラットな表現を使用する必要があります。

211
Tom Christie

@TomChristieありがとうございます!!!あなたは私をたくさん助けてくれました!私はそれを少し更新したいと思います(私が遭遇した間違いのため)

class TeacherSerializer(serializers.ModelSerializer):
    class Meta:
        model = Teacher
        fields = ('id', 'name', 'tenure')

class ClassroomSerializer(serializers.ModelSerializer):
    teachers = TeacherSerializer(source='teacher_set', many=True)

    class Meta:
        model = Classroom
        field = ("teachers",)
30
Eliyahu Tauber

これは drf-flex-fields と呼ばれる非常に便利なダンディDjangoパッケージを使用することでも実現できます。私たちはそれを使用し、それはかなり素晴らしいです。 pip install drf-flex-fieldsをインストールし、シリアライザーに渡して、expandable_fieldsとビンゴを追加します(下の例を参照)。また、ドット表記を使用して、深いネスト関係を指定できます。

from rest_flex_fields import FlexFieldsModelSerializer

class ClassroomSerializer(FlexFieldsModelSerializer):
    class Meta:
        model = Model
        fields = ("teacher_set",)
    expandable_fields = {"teacher_set": (TeacherSerializer, {"source": "teacher_set"})}

次に、?expand=teacher_setをURLに追加すると、拡張された応答が返されます。これがいつか誰かを助けることを願っています。乾杯!

0
Paul Tuckett