PĂ”hjalik juhend sisseehitatud objektide serialiseerimiseks Django REST Frameworkis (DRF), kasutades serialiseerijaid, hĂ”lmates erinevaid seoste tĂŒĂŒpe ja tĂ€iustatud tehnikaid.
Python DRF Serializer Relations: Sisseehitatud objektide serialiseerimise valdamine
Django REST Framework (DRF) pakub vĂ”imsa ja paindliku sĂŒsteemi veebi-API-de ehitamiseks. API arenduse oluline aspekt on andmemudelite vaheliste suhete kĂ€sitlemine ning DRF-i serialiseerijad pakuvad tugevaid mehhanisme sisseehitatud objektide serialiseerimiseks ja deserialiseerimiseks. See juhend uurib erinevaid viise suhete haldamiseks DRF-i serialiseerijates, pakkudes praktilisi nĂ€iteid ja parimaid tavasid.
Serialiseerija seoste mÔistmine
Relatsioonilistes andmebaasides mÀÀratlevad seosed, kuidas erinevad tabelid vĂ”i mudelid on ĂŒhendatud. DRF-i serialiseerijad peavad neid seoseid kajastama, kui andmebaasi objekte teisendatakse JSON-vormingusse vĂ”i muudesse andmevormingutesse API tarbimiseks. Me kĂ€sitleme kolme peamist seoste tĂŒĂŒpi:
- ForeignKey (ĂŒks-mitmele): Ăks objekt on seotud mitme muu objektiga. NĂ€iteks vĂ”ib ĂŒks autor kirjutada palju raamatuid.
- ManyToManyField (mitu-mitmele): Mitu objekti on seotud mitme muu objektiga. NÀiteks vÔivad mitu autorit teha koostööd mitme raamatu kallal.
- OneToOneField (ĂŒks-ĂŒhele): Ăks objekt on unikaalselt seotud teise objektiga. NĂ€iteks on kasutajaprofiil sageli ĂŒhendatud ĂŒks-ĂŒhele kasutajakontoga.
PÔhiline sisseehitatud serialiseerimine ForeignKeyga
Alustame lihtsa nÀitega ForeignKey seose serialiseerimisest. Vaatame neid mudeleid:
from django.db import models
class Author(models.Model):
name = models.CharField(max_length=100)
country = models.CharField(max_length=50, default='USA') # Lisades riigi vÀlja rahvusvahelise konteksti jaoks
def __str__(self):
return self.name
class Book(models.Model):
title = models.CharField(max_length=200)
author = models.ForeignKey(Author, on_delete=models.CASCADE, related_name='books')
publication_date = models.DateField()
def __str__(self):
return self.title
Raamatu `Book` serialiseerimiseks koos sellega seotud autori `Author` andmetega saame kasutada sisseehitatud serialiseerijat:
from rest_framework import serializers
class AuthorSerializer(serializers.ModelSerializer):
class Meta:
model = Author
fields = ['id', 'name', 'country']
class BookSerializer(serializers.ModelSerializer):
author = AuthorSerializer(read_only=True) # Muudetud PrimaryKeyRelatedFieldist
class Meta:
model = Book
fields = ['id', 'title', 'author', 'publication_date']
Selles nÀites sisaldab `BookSerializer` vÀlja `AuthorSerializer`. `read_only=True` muudab vÀlja `author` ainult loetavaks, takistades autori muutmist raamatu lÔpp-punkti kaudu. Kui teil on vaja luua vÔi vÀrskendada raamatuid autori teabega, peate kirjutamistoiminguid kÀsitlema erinevalt (vt allpool).
NĂŒĂŒd, kui serialiseerite objekti `Book`, sisaldab JSON-vĂ€ljund tĂ€ielikke autori andmeid, mis on raamatu andmetesse sisseehitatud:
{
"id": 1,
"title": "PöidlakĂŒĂŒdi reisijuht Galaktikas",
"author": {
"id": 1,
"name": "Douglas Adams",
"country": "UK"
},
"publication_date": "1979-10-12"
}
ManyToManyField seoste serialiseerimine
Vaatame `ManyToManyField` seost. Oletame, et meil on `Category` mudel ja raamat vÔib kuuluda mitmesse kategooriasse.
class Category(models.Model):
name = models.CharField(max_length=100)
def __str__(self):
return self.name
class Book(models.Model):
title = models.CharField(max_length=200)
author = models.ForeignKey(Author, on_delete=models.CASCADE, related_name='books')
categories = models.ManyToManyField(Category, related_name='books')
publication_date = models.DateField()
def __str__(self):
return self.title
Me saame serialiseerida kategooriaid kasutades `serializers.StringRelatedField` vÔi `serializers.PrimaryKeyRelatedField` vÔi luua sisseehitatud serialiseerija.
class CategorySerializer(serializers.ModelSerializer):
class Meta:
model = Category
fields = ['id', 'name']
class BookSerializer(serializers.ModelSerializer):
author = AuthorSerializer(read_only=True)
categories = CategorySerializer(many=True, read_only=True) # many=True on ManyToManyFieldi jaoks oluline
class Meta:
model = Book
fields = ['id', 'title', 'author', 'categories', 'publication_date']
Argument `many=True` on `ManyToManyField` serialiseerimisel ĂŒlioluline. See ĂŒtleb serialiseerijale, et ta ootaks kategooria objektide loendit. VĂ€ljund nĂ€eb vĂ€lja selline:
{
"id": 1,
"title": "Uhkus ja eelarvamus",
"author": {
"id": 2,
"name": "Jane Austen",
"country": "UK"
},
"categories": [
{
"id": 1,
"name": "Klassikaline kirjandus"
},
{
"id": 2,
"name": "Romantika"
}
],
"publication_date": "1813-01-28"
}
OneToOneField seoste serialiseerimine
`OneToOneField` seoste puhul on lÀhenemine sarnane ForeignKeyle, kuid oluline on kÀsitleda juhtumeid, kus seotud objekt ei pruugi eksisteerida.
from django.contrib.auth.models import User
class UserProfile(models.Model):
user = models.OneToOneField(User, on_delete=models.CASCADE, related_name='profile')
bio = models.TextField(blank=True)
location = models.CharField(max_length=100, blank=True, default='Global') # Lisatud asukoht rahvusvahelise konteksti jaoks
def __str__(self):
return self.user.username
class UserProfileSerializer(serializers.ModelSerializer):
class Meta:
model = UserProfile
fields = ['id', 'bio', 'location']
class UserSerializer(serializers.ModelSerializer):
profile = UserProfileSerializer(read_only=True)
class Meta:
model = User
fields = ['id', 'username', 'email', 'profile']
VĂ€ljund oleks:
{
"id": 1,
"username": "johndoe",
"email": "john.doe@example.com",
"profile": {
"id": 1,
"bio": "Tarkvara insener.",
"location": "London, UK"
}
}
Kirjutamistoimingute (loomine ja vÀrskendamine) kÀsitlemine
Ălaltoodud nĂ€ited keskenduvad peamiselt ainult loetavale serialiseerimisele. Seotud objektide loomiseks vĂ”i vĂ€rskendamiseks peate oma serialiseerijas ĂŒle kirjutama meetodid `create()` ja `update()`.
Sisseehitatud objektide loomine
Oletame, et soovite luua uue raamatu ja autori samaaegselt.
class BookSerializer(serializers.ModelSerializer):
author = AuthorSerializer()
class Meta:
model = Book
fields = ['id', 'title', 'author', 'publication_date']
def create(self, validated_data):
author_data = validated_data.pop('author')
author = Author.objects.create(**author_data)
book = Book.objects.create(author=author, **validated_data)
return book
Meetodis `create()` eraldame autori andmed, loome uue autori objekti `Author` ja seejÀrel loome raamatu objekti `Book`, sidudes selle Àsja loodud autoriga.
TÀhtis: Peate kÀsitlema vÔimalikke valideerimisvigu `author_data`. Saate kasutada try-except plokki ja tÔsta `serializers.ValidationError`, kui autori andmed on valed.
Sisseehitatud objektide vÀrskendamine
Sarnaselt, et vÀrskendada nii raamatut kui ka selle autorit:
class BookSerializer(serializers.ModelSerializer):
author = AuthorSerializer()
class Meta:
model = Book
fields = ['id', 'title', 'author', 'publication_date']
def update(self, instance, validated_data):
author_data = validated_data.pop('author', None)
if author_data:
author = instance.author
for attr, value in author_data.items():
setattr(author, attr, value)
author.save()
for attr, value in validated_data.items():
setattr(instance, attr, value)
instance.save()
return instance
Meetodis `update()` hangime olemasoleva autori, vĂ€rskendame selle atribuute vastavalt esitatud andmetele ja seejĂ€rel vĂ€rskendame raamatu atribuute. Kui `author_data` pole esitatud (mis tĂ€hendab, et autorit ei vĂ€rskendata), jĂ€tab kood autori vĂ€rskendamise osa vahele. VaikevÀÀrtus `None` vÀÀrtuses `validated_data.pop('author', None)` on ĂŒlioluline, et kĂ€sitleda juhtumeid, kus autori andmeid vĂ€rskendustaotluses ei ole.
`PrimaryKeyRelatedField` kasutamine
Sisseehitatud serialiseerijate asemel saate kasutada `PrimaryKeyRelatedField`, et esitada seoseid, kasutades seotud objekti primaarvÔtit. See on kasulik, kui teil on vaja ainult viidata seotud objekti ID-le ja te ei soovi kogu objekti serialiseerida.
class BookSerializer(serializers.ModelSerializer):
author = serializers.PrimaryKeyRelatedField(queryset=Author.objects.all())
class Meta:
model = Book
fields = ['id', 'title', 'author', 'publication_date']
NĂŒĂŒd sisaldab vĂ€li `author` autori ID-d:
{
"id": 1,
"title": "1984",
"author": 3, // Autori ID
"publication_date": "1949-06-08"
}
Loomise ja vÀrskendamise jaoks edastaksite autori ID taotluse andmetes. `queryset=Author.objects.all()` tagab, et esitatud ID on andmebaasis olemas.
`HyperlinkedRelatedField` kasutamine
`HyperlinkedRelatedField` esitab seoseid, kasutades hĂŒperlinke seotud objekti API lĂ”pp-punkti. See on tavaline hĂŒpermeedia API-des (HATEOAS).
class BookSerializer(serializers.ModelSerializer):
author = serializers.HyperlinkedRelatedField(view_name='author-detail', read_only=True)
class Meta:
model = Book
fields = ['id', 'title', 'author', 'publication_date']
Argument `view_name` mÀÀrab vaate nime, mis kÀsitleb seotud objekti taotlusi (nt `author-detail`). Peate selle vaate mÀÀratlema oma failis `urls.py`.
VÀljund sisaldab URL-i, mis viitab autori detailivaate lÔpp-punktile:
{
"id": 1,
"title": "Hea uus ilm",
"author": "http://example.com/api/authors/4/",
"publication_date": "1932-01-01"
}
TĂ€iustatud tehnikad ja kaalutlused
- `depth` Valik: Failis `ModelSerializer` saate kasutada valikut `depth`, et luua automaatselt sisseehitatud serialiseerijaid ForeignKey seostele kuni teatud sĂŒgavuseni. Kuid `depth` kasutamine vĂ”ib pĂ”hjustada jĂ”udlusprobleeme, kui seosed on keerulised, seega on ĂŒldiselt soovitatav serialiseerijad selgesĂ”naliselt mÀÀratleda.
- `SerializerMethodField`: Kasutage `SerializerMethodField`, et luua seotud andmete jaoks kohandatud serialiseerimisloogikat. See on kasulik, kui teil on vaja andmeid konkreetsel viisil vormindada vÔi lisada arvutatud vÀÀrtusi. NÀiteks saate kuvada autori tÀisnime erinevas jÀrjekorras, lÀhtudes lokaadist. Paljude Aasia kultuuride puhul on perekonnanimi enne eesnime.
- Esituse kohandamine: Kirjutage oma serialiseerijas ĂŒle meetod `to_representation()`, et kohandada seotud andmete esitusviisi.
- JĂ”udluse optimeerimine: Keeruliste seoste ja suurte andmekogumite puhul kasutage selliseid tehnikaid nagu select_related ja prefetch_related, et optimeerida andmebaasipĂ€ringuid ja vĂ€hendada andmebaasi tabamuste arvu. See on eriti oluline API-de puhul, mis teenindavad globaalseid kasutajaid, kellel vĂ”ivad olla aeglasemad ĂŒhendused.
- NullvÀÀrtuste kÀsitlemine: Olge teadlik sellest, kuidas nullvÀÀrtusi teie serialiseerijates kÀsitletakse, eriti valikuliste seoste korral. Vajadusel kasutage oma serialiseerija vÀljadel `allow_null=True`.
- Valideerimine: Rakendage tugev valideerimine, et tagada andmete terviklikkus, eriti seotud objektide loomisel vÔi vÀrskendamisel. Kaaluge kohandatud valideerijate kasutamist Àrireeglite jÔustamiseks. NÀiteks ei tohiks raamatu avaldamiskuupÀev olla tulevikus.
- Rahvusvahelistamine ja lokaliseerimine (i18n/l10n): Kaaluge, kuidas teie andmeid kuvatakse erinevates keeltes ja piirkondades. Vormindage kuupÀevi, numbreid ja valuutasid sobivalt kasutaja lokaadi jaoks. Salvestage rahvusvahelistatavad stringid oma mudelites ja serialiseerijates.
Serialiseerija seoste parimad tavad
- Hoidke serialiseerijad keskendunud: Iga serialiseerija peaks vastutama konkreetse mudeli vÔi tihedalt seotud andmekogumi serialiseerimise eest. VÀltige liiga keeruliste serialiseerijate loomist.
- Kasutage selgesĂ”nalisi serialiseerijaid: VĂ€ltige liigset tuginemist valikule `depth`. MÀÀratlege iga seotud mudeli jaoks selgesĂ”nalised serialiseerijad, et omada suuremat kontrolli serialiseerimisprotsessi ĂŒle.
- Testige pĂ”hjalikult: Kirjutage ĂŒhiku testid, et kontrollida, kas teie serialiseerijad serialiseerivad ja deserialiseerivad andmeid Ă”igesti, eriti keeruliste seoste korral.
- Dokumenteerige oma API: Dokumenteerige selgelt oma API lÔpp-punktid ja andmevormingud, mida nad ootavad ja tagastavad. Kasutage selliseid tööriistu nagu Swagger vÔi OpenAPI, et genereerida interaktiivne API dokumentatsioon.
- Kaaluge API versioonimist: Kuna teie API areneb, kasutage versioonimist, et sĂ€ilitada ĂŒhilduvus olemasolevate klientidega. See vĂ”imaldab teil tutvustada murrangulisi muudatusi, mĂ”jutamata vanemaid rakendusi.
- JÀlgige jÔudlust: JÀlgige oma API jÔudlust ja tuvastage kÔik serialiseerija seostega seotud kitsaskohad. Kasutage profileerimistööriistu andmebaasipÀringute ja serialiseerimisloogika optimeerimiseks.
JĂ€reldus
Serialiseerija seoste valdamine Django REST Frameworkis on oluline tugevate ja tĂ”husate veebi-API-de ehitamiseks. MĂ”istes erinevaid seoste tĂŒĂŒpe ja erinevaid DRF-i serialiseerijates saadaolevaid valikuid, saate tĂ”husalt serialiseerida ja deserialiseerida sisseehitatud objekte, kĂ€sitleda kirjutamistoiminguid ja optimeerida oma API-t jĂ”udluse saavutamiseks. Pidage meeles, et API kujundamisel tuleb arvestada rahvusvahelistamise ja lokaliseerimisega, et tagada selle kĂ€ttesaadavus globaalsele vaatajaskonnale. PĂ”hjalik testimine ja selge dokumentatsioon on vĂ”ti teie API pikaajalise hooldatavuse ja kasutatavuse tagamiseks.