Cadrul de odihnă Django (DRF) este unul dintre cadrele scrise în mod eficient în jurul Django și ajută la construirea API-urilor REST pentru o aplicație back-end.

Îl foloseam într-unul din proiectele mele personale și am dat peste această provocare de a „serializa un model care face referire la un alt model prin Câmp OneToOne. ”

„Foloseam Utilizator model din django.contrib.auth.models. Am vrut să scriu un API pentru a crea și actualiza un obiect utilizator printr-un singur API care actualizează și atributele modelului meu. Soluția a fost utilizarea DRF-urilor Relații imbricate în serializare.

Înainte de a continua, presupun că aveți cunoștințe corecte despre Python, virtualenv, pip, Django și DRF. Dacă nu, vă rugăm să aflați mai multe și nu ezitați să reveniți dacă sunteți blocat vreodată pe relații imbricate în serializare.

Exemplul pe care îl consider aici este un Student model, referință Utilizator model prin câmpul OneToOne. Obiectivul meu este un API unic pentru crearea și obținerea detaliilor utilizatorului, cum ar fi numele, numele de utilizator și e-mailul, împreună cu un atribut student, cum ar fi subiectul major.

Iată cum models.py arata:

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)

Apoi, serializatorul pentru modelul de mai sus determină atributele de manipulat. Dacă observați mai jos, am 2 clase de serializator, UserSerializer și StudentSerializer. Acesta este punctul nostru de interes.

Am declarat o user atribut care este un câmp serializator aici. Acea user atributul va deține în principal întreaga referință pentru UserSerializer clasă. În câmpuri de StudentSerializer , doar vedemuser‘ și ‘subject_major‘. Acest lucru ne permite să introducem atributele studentului (sau utilizatorului) împreună cu subject_major.

Se creează o intrare de utilizator la care se face referire prin intrarea de student. Înlocuim metoda de creare a StudentSerializer a crea un user obiect mai întâi și folosiți-l pentru a crea fișierul student obiect.

serializer.py este după cum urmează:

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 ar trebui să fie destul de simplu dacă sunteți deja familiarizat cu vizualizări bazate pe clasă de Django. Vom folosi serializatorul pentru a valida și a crea obiectele model:

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)

Am inclus /univstud/ url pentru realizare post și get cereri pentru student universitar.

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 cererea de apel ar arăta cam așa:

Relatii imbricate in serializatoare pentru campurile OneToOne din Django Rest
postare pentru / univstud /

Get cererea de apel ar arăta cam așa:

1611446104 676 Relatii imbricate in serializatoare pentru campurile OneToOne din Django Rest
primi apel pentru / univstud /

Asta e tot!:)

Relația imbricată este astfel activată pe StudentSerializer la referință user.

Codul complet este în gitlab-ul meu repertoriu.

Referințe:

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