Ένθετες σχέσεις σε σειριακούς για τα πεδία OneToOne στο Django Rest Framework

Το Django Rest Framework (DRF) είναι ένα από τα αποτελεσματικά γραμμένα πλαίσια γύρω από το Django και βοηθά στη δημιουργία REST APIs για ένα back-end εφαρμογής.

Το χρησιμοποιούσα σε ένα από τα προσωπικά μου έργα και έπεσα σε αυτήν την πρόκληση της «σειριοποίησης ενός μοντέλου που αναφέρεται σε άλλο μοντέλο μέσω του πεδίου OneToOne»

«Χρησιμοποιούσα το μοντέλο χρήστη από django.contrib.auth.models. Ήθελα να γράψω ένα 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)

Στη συνέχεια, το πρόγραμμα σειριοποίησης για το παραπάνω μοντέλο καθορίζει τα χαρακτηριστικά που πρέπει να χειριστείτε. Αν παρατηρήσετε παρακάτω, έχω 2 σειρές σειριοποιητή,UserSerializerκαι StudentSerializer.Αυτό είναι το σημείο ενδιαφέροντος μας.

Έχω δηλώσει ένα userχαρακτηριστικό που είναι πεδίο σειριοποίησης εδώ. Αυτό το userχαρακτηριστικό διατηρεί κυρίως ολόκληρη την αναφορά για την UserSerializerτάξη. Στα πεδία του StudentSerializer, βλέπουμε απλώς ' user' και ' subject_major'. Αυτό μας επιτρέπει να εισαγάγουμε τις ιδιότητες μαθητή (ή χρήστη) μαζί με το subject_major.

Δημιουργείται μια καταχώριση χρήστη η οποία αναφέρεται από την καταχώρηση του μαθητή. Παρακάμπτουμε τη μέθοδο δημιουργίας για StudentSerializerνα δημιουργήσουμε 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

Το views.pyθα πρέπει να είναι αρκετά απλό εάν είστε ήδη εξοικειωμένοι με τις απόψεις του Django με βάση την τάξη. Θα χρησιμοποιήσουμε το πρόγραμμα σειριοποίησης για επικύρωση και δημιουργία αντικειμένων μοντέλου:

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)

Έχω συμπεριλάβει /univstud/url για επίτευξη postκαι getαιτήματα για φοιτητή πανεπιστημίου.

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.

Βιβλιογραφικές αναφορές:

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