I want to add json data from the listserializer to the DetailSerializer class. The serializer looks something like this:
serializer.py
class ListSerializer(serializers.ModelSerializer):
class Meta:
model = Fastest_laps
fields = '__all__'
class DetailSerializer(serializers.ModelSerializer):
listserializer = ListSerializer( read_only=True, many=True)
class Meta:
model = Driver
fields =
('place_of_birth','driver','listserializer','picture')
But i dont really see the data once i view it, i only see the detailserializer data( Driver model)
class Fastest_laps(models.Model):
driver_name = models.CharField(max_length=25, null=True)
grand_prix = models.CharField(max_length=15, blank=True)
car_model = models.CharField(max_length=50)
time_taken = models.CharField(blank=True, max_length=8)
def __str__(self):
return self.driver_name
class Driver(models.Model):
place_of_birth = models.CharField(max_length=25)
driver = models.ForeignKey(Fastest_laps,
db_column='driver_name')
picture = models.ImageField(blank=True, null=True)
def __str__(self):
return str(self.driver)
api.py
class FastLapsSet(ModelViewSet):
queryset = Fastest_laps.objects.all()
serializer_class = ListSerializer
class DriverSet(ModelViewSet):
queryset = Driver.objects.all()
serializer_class = DetailSerializer
you should rename your property as model name field:
class DetailSerializer(serializers.ModelSerializer):
driver = ListSerializer(read_only=True)
# ^^^
class Meta:
model = Driver
fields =
('place_of_birth','driver','driver','picture')
or add the source attribute:
class DetailSerializer(serializers.ModelSerializer):
listserializer = ListSerializer(source='driver', read_only=True)
#^^^^
class Meta:
model = Driver
fields =
('place_of_birth','driver','listserializer','picture')
Related
I have this model that represents a bookmark or favorite. It has multiple foreign keys to other models. In the api I would like to pull in the data from each of the models that is referenced in the particular bookmark.
The model:
class Bookmark(models.Model):
marktype = models.CharField(max_length=10)
post = models.OneToOneField(Post, on_delete=models.CASCADE, null=True, blank=True)
question = models.OneToOneField(Question, on_delete=models.CASCADE, null=True, blank=True)
owner = models.ForeignKey(User, on_delete=models.CASCADE)
created_at = models.DateTimeField(auto_now_add=True, verbose_name="created at")
updated_at = models.DateTimeField(auto_now=True, verbose_name="updated at")
class Meta:
verbose_name = "bookmark"
verbose_name_plural = "bookmarks"
ordering = ["created_at"]
db_table = "bookmarks"
def __str__(self):
return "{}'s bookmark".format(self.owner.username)
I tried to use a SerializerMethodField but I get an error: 'NoneType' object has no attribute 'id'
Here is the serializer
class BookmarkSerializer(serializers.ModelSerializer):
post = serializers.SerializerMethodField()
question = serializers.SerializerMethodField()
class Meta:
model = Bookmark
fields = '__all__'
def get_post(self, obj):
obj = Post.objects.get(id=obj.post.id)
post = ShortPostSerializer(obj)
return post.data
def get_question(self, obj):
obj = Question.objects.get(id=obj.question.id)
question = ShortQuestionSerializer(obj)
return question.data
what am I doing wrong please?
You can update your serializer like the following (You can short it as you want or use your ShortQuestionSerializer as well instead of QuestionSerializer),
class QuestionSerializer(serializers.ModelSerializer):
class Meta:
model = Question
fields = '__all__'
class PostSerializer(serializers.ModelSerializer):
class Meta:
model = Post
fields = '__all__'
class BookmarkSerializer(serializers.ModelSerializer):
post = PostSerializer()
question = QuestionSerializer()
class Meta:
model = Bookmark
fields = '__all__'
I have 3 models:
class Artist(Timestamps):
name = models.CharField('Name', max_length=255, blank=True)
...
class Festival(Timestamps):
name = models.CharField(max_length=255, blank=True)
...
class Event(Timestamps):
artist = models.ForeignKey(Artist, on_delete=models.CASCADE, null=True)
festival = models.ForeignKey(Festival, on_delete=models.CASCADE, null=True)
Now I wan't all the id's from the festivals an artist is playing. I have a serializer like this:
class ArtistFestivalSerializer(serializers.ModelSerializer):
class Meta:
model = Artist
fields = ('id', 'name', 'event_set')
But this only gives me the id's of the event. Any ideas how to get trough the Event to the Festival?
Thanks in advance
EDIT - the view is:
class FestivalArtists(generics.ListAPIView):
serializer_class = ArtistFestivalSerializer
def get_queryset(self):
queryset = Artist.objects.prefetch_related('event_set').filter(event__isnull=False).distinct().order_by('name')
return queryset
I think you need to add the custom field for that.
class ArtistFestivalSerializer(serializers.ModelSerializer):
festival_ids = serializers.SerializerMethodField(read_only = True)
class Meta:
model = Artist
fields = ('id', 'name', 'event_set', 'festival_ids')
def get_festival_ids(self, obj):
return list(Event.objects.filter(artist = obj).values_list('festival_id').distinct())
I am working just for my experience and I stacked with the following problem. There are three models: Book, Chapter, and Publisher. Each model is related to one another with the foreign key.
class Book(models.Model):
name = models.CharField(max_length=64)
publisher = models.ForeignKey('Publisher', on_delete=models.CASCADE, null=True, blank=True)
def __str__(self):
return self.name
class Chapter(models.Model):
name = models.CharField(max_length=128)
book = models.ForeignKey(Book, related_name='books', on_delete=models.CASCADE)
class Publisher(models.Model):
title = models.CharField(max_length=128)
description = models.TextField()
def __str__(self):
return self.title
class Meta:
ordering = ['title']
I want to serialize the data in PublisherDetailSerializer which should show their books and all chapters related to their books.
Here are my serializers:
class BookSerializer(serializers.ModelSerializer):
class Meta:
model = Book
fields = ('id', 'name', 'publisher')
def to_representation(self, instance):
ret = super().to_representation(instance)
return ret
class ChapterSerializer(serializers.ModelSerializer):
id = serializers.IntegerField()
name = serializers.CharField(required=False)
location = serializers.SerializerMethodField()
class Meta:
model = Chapter
fields = ('id', 'name', 'location')
def get_location(self, instance):
serializer = BookSerializer(instance.author, context=self.context)
return serializer.data
class PublisherSerializer(serializers.HyperlinkedModelSerializer):
books = BookSerializer(many=True, read_only=True)
class Meta:
model = Publisher
fields = ('id', 'title', 'description', 'books')
class PublisherDetailSerializer(PublisherSerializer):
chapters = serializers.SerializerMethodField()
class Meta:
model = Publisher
fields = ('id', 'title', 'description', 'books', 'chapters')
def get_chapters(self, instance):
serializer = ChapterSerializer(Chapter.objects.filter(location=instance.books.name), many=True, context=self.context)
return serializer.data
def to_representation(self, instance):
ret = super().to_representation(instance)
return ret
Here is my view for Publisher:
class PublisherViewSet(MultiSerializerViewSetMixin, viewsets.ReadOnlyModelViewSet):
queryset = Publisher.objects.all()
serializer_class = PublisherSerializer
serializer_action_classes = {
'list': PublisherSerializer,
'retrieve': PublisherDetailSerializer,
}
Showing publishers and their books shows the right information in the browsable API, but I don't know how to get chapters through books. How should I approach it?
Notes:
the related_name in a models.ForeignKey is not what you thing it is. it is the attribute name to be used on the otherside of the relationship, see the below code
you can just nest the serializers as shown below
Models
class Publisher(models.Model):
title = models.CharField(max_length=128)
description = models.TextField()
class Book(models.Model):
name = models.CharField(max_length=128)
publisher = models.ForeignKey(Publisher, related_name='books', on_delete=models.CASCADE)
class Chapter(models.Model):
name = models.CharField(max_length=128)
book = models.ForeignKey(Book, related_name='chapters', on_delete=models.CASCADE)
Serializers
class ChapterSerializer(serializers.ModelSerializer):
id = serializers.IntegerField()
name = serializers.CharField(required=False)
class Meta:
model = Chapter
fields = ('id', 'name')
class BookSerializer(serializers.ModelSerializer):
chapters = ChapterSerializer(many=True, read_only=True)
class Meta:
model = Book
fields = ('id', 'name', 'chapters')
class PublisherSerializer(serializers.HyperlinkedModelSerializer):
books = BookSerializer(many=True, read_only=True)
class Meta:
model = Publisher
fields = ('id', 'title', 'description', 'books')
Trying to add 3rd nested serializer using django rest framework
how to add 3rd nested realation in given code -
models.py
class Category(models.Model):
cate_id = models.AutoField(primary_key=True)
cate_name = models.CharField(max_length=45)
class Meta:
managed = False
db_table = 'category'
class SubCategory(models.Model):
sub_cate_id = models.AutoField(primary_key=True)
sub_cate_name = models.CharField(max_length=45)
sub_fk = models.ForeignKey('Category', models.CASCADE, db_column='sub_fk')
class Meta:
managed = False
db_table = 'sub_category'
class Products(models.Model):
pro_id = models.AutoField(primary_key=True)
pro_name = models.CharField(max_length=45)
description = models.CharField(max_length=45, blank=True, null=True)
price = models.IntegerField()
quantity = models.IntegerField()
pro_cate_fk = models.ForeignKey('Category', models.CASCADE, db_column='pro_cate_fk')
pro_sub_fk = models.ForeignKey('SubCategory', models.CASCADE, db_column='pro_sub_fk')
image = models.CharField(max_length=205)
class Meta:
managed = False
db_table = 'products'
from rest_framework import serializers
from .models import Category,SubCategory,Products
class ProductsSerializer(serializers.ModelSerializer):
# x= ChildTable.objects.all().values
class Meta:
model = Products
fields = ('pro_id','pro_name','description','price','quantity','image')
class SubCategorySerializer(ProductsSerializer):
products_set = ProductsSerializer(many=True, read_only=True)
class Meta:
model = SubCategory
fields = ('sub_cate_name','sub_cate_id','products_set')
class CategorySerializer(SubCategorySerializer):
subcategory_set = ProductsSerializer(many=True, read_only=True,)
# pro_subcate_set = SubCategorySerializer(many=True, read_only=True)
class Meta:
model = Category
fields = ('cate_name','cate_id','subcategory_set')
Got this error while attempting -
Got AttributeError when attempting to get a value for field `pro_name` on serializer `ProductsSerializer`. The serializer field might be named incorrectly and not match any attribute or key on the `SubCategory` instance. Original exception text was: 'SubCategory' object has no attribute 'pro_name'.
Is it possible to connect 2 already connected serializer to another serializer?
Make a test and see if it works.
class CategorySerializer(serializers.ModelSerializer):
class Meta:
model = Category
fields = ('cate_id', 'cate_name')
class SubCategorySerializer(serializers.ModelSerializer):
class Meta:
model = SubCategory
fields = ('sub_cate_id', 'sub_cate_name', 'sub_fk')
def to_representation(self, instance):
response = super().to_represntation(instance)
response['sub_fk'] = CategorySerializer(instance.sub_fk).data
return response
class ProductSerializer(serializers.ModelSerializer):
class Meta:
model = Products
fields = ('pro_id', 'pro_name', 'description', 'price', 'quantity', 'pro_cate_fk', 'pro_sub_fk', 'image')
def to_representation(self, instance):
response = super().to_representation(instance)
response['pro_cate_fk'] = CategorySerializer(instance.pro_cate_fk).data
response['pro_sub_fk'] = ProductSerializer(instance.pro_sub_fk).data
return response
I have seen some related posts, but I am not sure what I need to do.
I have set up a view to serialize my test model which has nested models. I have set up the serializers, but I get the error "Got AttributeError when attempting to get a value for field Question on serializer TestSerializer.\nThe serializer field might be named incorrectly".
My Serializers:
class AnswerSerializer(serializers.ModelSerializer):
class Meta:
model = Answer
fields = ('id', 'number', 'text', 'iscorrect')
class QuestionSerializer(serializers.ModelSerializer):
answer = AnswerSerializer()
class Meta:
model = Question
fields = ('id', 'number', 'text', 'answer')
related_object = 'answer'
class TestSerializer(serializers.ModelSerializer):
question = QuestionSerializer()
class Meta:
model = Test
fields = ('id', 'name', 'question')
related_object = 'question'
My Models:
class Test(models.Model):
user = models.ForeignKey(User, on_delete=models.PROTECT)
name = models.CharField(max_length=255,default='',blank=False)
datecreated = models.DateTimeField(auto_now=True)
def __str__(self):
return self.name
class Question(models.Model):
test = models.ForeignKey(Test, on_delete=models.CASCADE)
text = models.CharField(max_length=255,default='',blank=False)
number = models.IntegerField()
def __str__(self):
return self.text
class Answer(models.Model):
question = models.ForeignKey(Question, on_delete=models.CASCADE)
text = models.CharField(max_length=255,default='',blank=False)
number = models.IntegerField()
iscorrect = models.BooleanField(default=False)
def __str__(self):
return self.text
The call from the view:
serializer = TestSerializer(test, many=True)
You have set the related_name in the foreign key other wise default related name is {model_name}_set.
class Question(models.Model):
test = models.ForeignKey(Test, on_delete=models.CASCADE, related_name='questions')
text = models.CharField(max_length=255,default='',blank=False)
number = models.IntegerField()
def __str__(self):
return self.text
in serializer you can access that fields
class TestSerializer(serializers.ModelSerializer):
questions = QuestionSerializer(many=True)
class Meta:
model = Test
fields = ('id', 'name', 'question')
related_object = 'question'