Ugniježđene veze u serilizatorima za polja OneToOne u Django Rest Framework

Django Rest Framework (DRF) jedan je od učinkovito napisanih okvira oko Djanga i pomaže u izgradnji REST API-ja za pozadinu aplikacije.

Koristio sam ga u jednom od svojih osobnih projekata i nabasao na ovaj izazov "serializiranja modela koji referencira drugi model putem polja OneToOne."

`Koristio sam model korisnika iz django.contrib.auth.models. Htio sam napisati API za stvaranje i ažuriranje korisničkog objekta kroz jedan API koji također ažurira atribute mog modela. Rješenje je bilo koristiti ugniježđene odnose DRF-a u serializaciji.

Pretpostavit ću da dobro poznajete Python, virtualenv, pip, Django i DRF prije nego što nastavite. Ako ne, naučite više i slobodno se vratite ako ikad zapnete u ugniježđenim odnosima u serializaciji.

Primjer koji ovdje razmatram je model sveučilišnog studenta koji se poziva na model korisnika putem polja OneToOne. Moj je cilj jedinstveni API za stvaranje i dobivanje korisničkih podataka poput imena, korisničkog imena i e-pošte, zajedno s atributom učenika, kao što je glavni predmet.

Evo kako models.pyizgleda moj izgled:

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)

Dalje, serializator za gornji model određuje atribute kojima će se manipulirati. Ako primijetite dolje, imam 2 klase serializatora,UserSerializeri StudentSerializer.To je naša točka interesa.

Proglasio sam useratribut koji je ovdje polje serializatora. Taj userće atribut primarno sadržavati cijelu referencu za UserSerializerklasu. U područjima u StudentSerializer, možemo samo vidjeti „ user” i „ subject_major”. To nam omogućuje da unesemo atribute učenika (ili korisnika) zajedno s subject_major.

Stvara se korisnički unos na koji referencira unos učenika. Nadjačavamo metodu stvaranja da StudentSerializerbismo userprvo stvorili objekt i koristimo je za stvaranje studentobjekta.

Slijedi serializer.py sljedeće:

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

views.pyTreba prilično jednostavan, ako ste već upoznati s pogledom klase na bazi od Django. Koristit ćemo serializator za provjeru valjanosti i stvaranje objekata modela:

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)

Uključio sam /univstud/url za postizanje posti getzahtjeve za studente.

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"), ])

Poziv POSTzahtjeva izgledao bi otprilike ovako:

Poziv Getzahtjeva izgledao bi otprilike ovako:

To je sve!:)

Ugnježđeni odnos je tako omogućen na StudentSerializerreferenci user.

Kompletni kôd nalazi se u mom gitlab spremištu.

Reference:

  1. //www.django-rest-framework.org/api-guide/relations/