Django Rest Framework の OneToOne フィールドのシリアライザーでのネストされた関係
Django Rest Framework (DRF) は、Django を中心に効率的に作成されたフレームワークの 1 つで、アプリケーション バックエンド用の REST API の構築に役立ちます。
私は個人プロジェクトの 1 つでこれを使用していたときに、「OneToOne フィールドを介して別のモデルを参照しているモデルをシリアル化する」という課題に遭遇しました。 」
` django.contrib.auth.models
の User model を使用していました。単一の API を通じてユーザー オブジェクトを作成および更新し、モデルの属性も更新する API を作成したいと考えていました。解決策は、シリアル化で DRF のネストされた関係を使用することでした。
続行する前に、Python、virtualenv、pip、Django、および DRF について十分な実用的な知識があることを前提とします。そうでない場合は、さらに詳しく学んで、連載中のネストされた関係に行き詰まった場合には、お気軽に戻ってください。
ここで検討している例は、OneToOne フィールドを介してユーザーモデルを参照する大学生モデルです。私の目標は、名前、ユーザー名、電子メールなどのユーザーの詳細と、専攻科目などの学生属性を作成および取得する単一の API です。
私の models.py
は次のようになります。
from django.db import models
from django.contrib.auth.models import User
class UnivStudent(models.Model):
"""
A class based model for storing the records of a university student
Note: A OneToOne relation is established for each student with User model.
"""
user = models.OneToOneField(User)
subject_major = models.CharField(name="subject_major", max_length=60)
次に、上記のモデルのシリアライザーは、操作する属性を決定します。以下を見ると、UserSerializer
と StudentSerializer
という 2 つのシリアライザー クラスがあることがわかります。 これが私たちの関心事です。
ここではシリアライザーフィールドである user
属性を宣言しました。その user
属性は、主に UserSerializer
クラスの参照全体を保持します。 StudentSerializer
のフィールドには、「user
」と「subject_major
」だけが表示されます。これにより、subject_major とともに学生 (またはユーザー) 属性を入力できるようになります。
学生エントリによって参照されるユーザー エントリが作成されます。 StudentSerializer
の create メソッドをオーバーライドして、最初に user
オブジェクトを作成し、それを使用して student
オブジェクトを作成します。
serializer.py
は次のとおりです。
from rest_framework import serializers, status
from models import *
class UserSerializer(serializers.ModelSerializer):
class Meta:
model = User
fields = ('username', 'first_name', 'last_name', 'email')
class StudentSerializer(serializers.ModelSerializer):
"""
A student serializer to return the student details
"""
user = UserSerializer(required=True)
class Meta:
model = UnivStudent
fields = ('user', 'subject_major',)
def create(self, validated_data):
"""
Overriding the default create method of the Model serializer.
:param validated_data: data containing all the details of student
:return: returns a successfully created student record
"""
user_data = validated_data.pop('user')
user = UserSerializer.create(UserSerializer(), validated_data=user_data)
student, created = UnivStudent.objects.update_or_create(user=user,
subject_major=validated_data.pop('subject_major'))
return student
Django のクラスベースのビューにすでに慣れている場合、views.py
は非常に簡単です。シリアライザーを使用してモデル オブジェクトを検証し、作成します。
from serializers import *
from models import *
from rest_framework.views import APIView
from rest_framework.response import Response
from rest_framework import status
class StudentRecordView(APIView):
"""
A class based view for creating and fetching student records
"""
def get(self, format=None):
"""
Get all the student records
:param format: Format of the student records to return to
:return: Returns a list of student records
"""
students = UnivStudent.objects.all()
serializer = StudentSerializer(students, many=True)
return Response(serializer.data)
def post(self, request):
"""
Create a student record
:param format: Format of the student records to return to
:param request: Request object for creating student
:return: Returns a student record
"""
serializer = StudentSerializer(data=request.data)
if serializer.is_valid(raise_exception=ValueError):
serializer.create(validated_data=request.data)
return Response(serializer.data, status=status.HTTP_201_CREATED)
return Response(serializer.error_messages,
status=status.HTTP_400_BAD_REQUEST)
大学生の post
リクエストと get
リクエストを達成するための /univstud/
url
を含めました。
from django.conf.urls import patterns, include, url
from django.contrib import admin
from rest_framework import routers
from rest_framework.urlpatterns import format_suffix_patterns
from OneToOne import views
admin.autodiscover()
router = routers.DefaultRouter()
urlpatterns = patterns('',
url(r'^admin/', include(admin.site.urls)),
url(r'^api-auth/', include('rest_framework.urls',
namespace='rest_framework')),
)
urlpatterns += format_suffix_patterns([
# API to map the student record
url(r'^api/univstud/$',
views.StudentRecordView.as_view(),
name='students_list'),
])
POST
リクエストの呼び出しは次のようになります。
Get
リクエストの呼び出しは次のようになります。
それだけです!:)
したがって、StudentSerializer
でネストされた関係が有効になり、user
を参照します。
完全なコードは私の gitlab リポジトリにあります。
参考文献:
- http://www.django-rest-framework.org/api-guide/relations/