Indlejrede forhold i Serializers til OneToOne-felter i Django Rest Framework

Django Rest Framework (DRF) er en af ​​de effektivt skrevne rammer omkring Django og hjælper med at opbygge REST API'er til en applikationsback-end.

Jeg brugte det i et af mine personlige projekter og snublede over denne udfordring med at "serialisere en model, der henviser til en anden model via OneToOne-feltet."

`Jeg var ved hjælp af User model fra django.contrib.auth.models. Jeg ville skrive en API for at oprette og opdatere et brugerobjekt gennem en enkelt API, som også opdaterer min models attributter. Løsningen var at bruge DRFs indlejrede forhold i serialisering.

Jeg antager, at du har en god arbejdskendskab til Python, virtualenv, pip, Django og DRF, før du fortsætter. Hvis ikke, bedes du lære mere, og du er velkommen til at vende tilbage, hvis du nogensinde sidder fast i indlejrede forhold i serialisering.

Eksemplet jeg overvejer her er en University Student model, refererer Bruger model via OneToOne feltet. Mit mål er en enkelt API til oprettelse og hentning af brugeroplysninger som navn, brugernavn og e-mail sammen med en elevattribut som emneopgave.

Sådan models.pyser jeg ud:

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)

Dernæst bestemmer serialisereren til ovenstående model de attributter, der skal manipuleres. Hvis du observerer nedenfor, har jeg to serialiseringsklasser,UserSerializerog StudentSerializer.Dette er vores interessepunkt.

Jeg har erklæret en userattribut, der er et serialiseringsfelt her. Denne userattribut vil primært indeholde hele referencen for UserSerializerklassen. I felterne af StudentSerializerser vi bare ' user' og ' subject_major'. Dette giver os mulighed for at indtaste attributterne student (eller bruger) sammen med subject_major.

Der oprettes en brugerindgang, der refereres til af studerendeindgangen. Vi tilsidesætter oprettelsesmetoden for StudentSerializerat oprette et userobjekt først og bruger den til at oprette studentobjektet.

Det serializer.py er som følger:

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

Det views.pyburde være ret ligetil, hvis du allerede er bekendt med de klassebaserede synspunkter på Django. Vi bruger serializer til at validere og oprette modelobjekter:

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)

Jeg har medtaget /univstud/url for at opnå postog getanmodninger om universitetsstuderende.

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

Den POSTanmodning opkald ville se nogenlunde sådan her:

Den Getanmodning opkald ville se nogenlunde sådan her:

Det er alt!:)

Nestet forhold er således aktiveret StudentSerializertil reference user.

Komplet kode findes i mit gitlab-lager.

Referencer:

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