Reputation: 1554
I'm new to Python, and I guess I'm serializing it incorrectly.
authors/models.py:
from django.db import models
from django.contrib.auth.models import User
# Create your models here.
class Author(models.Model):
name = models.CharField(max_length=100)
def __str__(self):
return self.name
class Book(models.Model):
auto_increment_id = models.AutoField(primary_key=True)
name = models.CharField('Book name', max_length=100)
author = models.ForeignKey(Author, blank=False, null=False, related_name='book_author')
contents = models.TextField('Contents', blank=False, null=False)
def __str__(self):
return self.name
authors/views.py
from authors.models import Book, Author
from authors.serializers import BookSerializer, AuthorSerializer
from django.shortcuts import render
from rest_framework import generics
class ListCreateBooks(generics.ListCreateAPIView):
queryset = Book.objects.all()
serializer_class = BookSerializer
class ListCreateAuthor(generics.ListCreateAPIView):
queryset = Author.objects.all()
serializer_class = AuthorSerializer
authors/serializers.py
from authors.models import Book, Author
from rest_framework import serializers
class BookSerializer(serializers.ModelSerializer):
class Meta:
model = Book
fields = ('name', 'author')
class AuthorSerializer(serializers.ModelSerializer):
class Meta:
model = Author
book_author = 'name'
I'm new to Django, but I tried many things, in my views.py I've added another class called AuthorSerializer
importing from a corresponding class I created in serializers, but then I realized that I have no clue how to add my ListCreateAuthor
to:
url(r'^api-auth/', ListCreateBooks.as_view(), name='list_books')
I've added another parameter with ListCreateAuthor.as_view()
that gave me an immediate error (and which also didn't make much sense) Am I going the wrong way here and how can I solve this?
EDIT: @Abdulafaja gave a partial answer, which did solve the read, but now after checking a POST insert - it gives an error for create or update.
in Django rest_framework's documentation (link provided by @Abdulafaja) it give only one example for a nested serializer, and it's a one to many relationship (Album->tracks) but mine is one to one (book->author) so I have no idea how to serilize the nested feature. This API needs to give the frontend all CRUD features.
Thanks.
EDITED serializers.py by Abdullah:
from authors.models import Book, Author
from rest_framework import serializers
class AuthorSerializer(serializers.ModelSerializer):
class Meta:
model = Author
book_author = 'name'
class BookSerializer(serializers.ModelSerializer):
author = AuthorSerializer(many=False)
class Meta:
model = Book
fields = ('name', 'author')
def create(self, validated_data):
author, _ = Author.objects.get_or_create(name=validated_data.get('author').get('name'))
return Book.objects.create(name=validated_data.get('name'), author=author)
def update(self, instance, validated_data):
author = validated_data.get('author')
if author:
instance.author = Author.objects.get_or_create(name=author.get('name'))
instance.name = validated_data.get('name', instance.name)
instance.save()
return instance
Upvotes: 1
Views: 1289
Reputation: 561
From my understanding you wish to get details of Authors in the api request not just their number??
The way to do that is to set the depth in your model serializer.
class BookSerializer(serializers.ModelSerializer):
class Meta:
model = Book
fields = ('name', 'author')
depth=1
The depth option should be set to an integer value that indicates the depth of relationships that should be traversed before reverting to a flat representation. i.e. 1, 2, 3...
source: http://www.django-rest-framework.org/api-guide/serializers/
Upvotes: 3
Reputation: 261
For Book model Author is just an id of that field in database, so that's why it's return an integer field. Try to add an Author field in Book serializer
class BookSerializer(serializers.ModelSerializer):
author = AuthorSerializer(read_only=True)
class Meta:
model = Book
fields = ('name', 'author')
This is a NestedSerializer, which is read-only by default. On it's DRF doc site link is mentioned that you
need to create create() and/or update() methods in order to explicitly specify how the child relationships should be saved.
So your BookSerializer needs to look like this
class BookSerializer(serializers.ModelSerializer):
author = AuthorSerializer(read_only=True)
class Meta:
model = Book
fields = ('name', 'author')
def create(self, validated_data):
# Create new object
def update(self, instance, validated_data):
# Update existing instance
Both create
and update
methods need to save the object to the database and return it. There are called when you save your BookSerializer class instance.
The difference between them is that create
is called when you create new instance of Book object
serializer = BookSerializer(data=data)
and update
is called if you passed an existing instance of Book object when instantiating the serializer class
serializer = BookSerializer(book, data=data)
More information you can find here
EDIT: If you want to create an instance with NestedSerializer it should not be read only field.
class BookSerializer(serializers.ModelSerializer):
author = AuthorSerializer(many=False)
class Meta:
model = Book
fields = ('name', 'author')
def create(self, validated_data):
author, _ = Author.objects.get_or_create(name=validated_data.get('author').get('name'))
return Book.objects.create(name=validated_data.get('name'), author=author)
def update(self, instance, validated_data):
author = validated_data.get('author')
if author:
instance.author = Author.objects.get_or_create(name=author.get('name'))
instance.name = validated_data.get('name', instance.name)
instance.save()
return instance
Upvotes: 1