I have models,
class Reporter(models.Model):
name = models.CharField(max_length=50)
def __str__(self):
return self.name
class Article(models.Model):
title = models.CharField(max_length=100)
reporter = models.ForeignKey(Reporter, on_delete=models.CASCADE)
def __str__(self):
return self.title
and serializer,
class ReporterSerializer(serializers.ModelSerializer):
article = serializers.StringRelatedField(source='article_set')
class Meta:
model = Reporter
fields = '__all__'
and views
class ReporterAPI(viewsets.ModelViewSet):
queryset = Reporter.objects.all()
serializer_class = ReporterSerializer
Everything seems fine, but, my response showing something weird
response
Here is the RESPONSE IMAGE
The response article is showing wrong output
Since article_set is list of objects you should add many=True argument:
class ReporterSerializer(serializers.ModelSerializer):
article = serializers.StringRelatedField(source='article_set', many=True)
class Meta:
model = Reporter
fields = '__all__'
Related
I was trying to update an M2M field but it just doesn't get updated neither from admin panel nor the serializer!
We have a "Book" model which has a "Category" field that is M2M to BookCategory Model
this is my model:
class Book(models.Model):
#...
category = models.ManyToManyField('BookCategory', related_name='bookCategory')
def __str__(self):
return self.name
class BookCategory(models.Model):
name = models.CharField(max_length=100)
parent = models.ForeignKey('BookCategory', on_delete=models.PROTECT, null=True, blank=True)
description = models.TextField()
def __str__(self):
return self.name
and this is my view:
class BookChange(RetrieveUpdateDestroyAPIView):
serializer_class = BookSerializer
lookup_field = 'pk'
def get_queryset(self):
return Book.objects.all()
and the Model Serializer:
class BookSerializer(serializers.ModelSerializer):
class Meta:
model = Book
fields = '__all__'
The funny thing is that when I remove the current category it works but it doesn't add the new ones
I also tried Overriding the serializer.save() in def update
Can you help me out?
Get method working in browse-able api end-point but when i try to post using my end-point through browser, it fires me this error: (My serializers are nested)
This is my serializers.py and it is Nested serilizers
from rest_framework import serializers
from . models import Author, Article, Category, Organization
class OrganizationSerializer(serializers.ModelSerializer):
class Meta:
model = Organization
fields = '__all__'
class AuthorSerializer(serializers.ModelSerializer):
organization = OrganizationSerializer()
class Meta:
model = Author
fields = '__all__'
class CategorySerializer(serializers.ModelSerializer):
class Meta:
model = Category
fields = '__all__'
class ArticleSerializer(serializers.ModelSerializer):
author = AuthorSerializer()
category = CategorySerializer()
class Meta:
model = Article
fields = '__all__'
and this is my models.py
from django.db import models
import uuid
class Organization(models.Model):
organization_name = models.CharField(max_length=50)
contact = models.CharField(max_length=12, unique=True)
def __str__(self):
return self.organization_name
class Author(models.Model):
name = models.CharField(max_length=40)
detail = models.TextField()
organization = models.ForeignKey(Organization, on_delete=models.DO_NOTHING)
def __str__(self):
return self.name
class Category(models.Model):
name = models.CharField(max_length=100)
def __str__(self):
return self.name
class Article(models.Model):
alias = models.UUIDField(primary_key=True, default=uuid.uuid4, editable=False)
author = models.ForeignKey(Author, on_delete=models.CASCADE, related_name='author')
title = models.CharField(max_length=200)
body = models.TextField()
category = models.ForeignKey(Category, on_delete=models.CASCADE)
and this is my views.py ( I am using APIView, not VIewset)
class ArticleDeleteUpdate(DestroyAPIView, UpdateAPIView):
queryset = Article.objects.all()
serializer_class = ArticleSerializer
lookup_field = 'alias'
and this is my urls.py
path('api/v1/article', views.ArticleListCreateGet.as_view(), name='article2'),
I worked 10 hours on it to fix the issue but i failed to fix it...
I am not getting whats wrong with this... this error ruined my sleep..
Can anyone help me please to fix this issue?
EDIT with the correct approach:
Sorry I just realized you are using ModelSerializers instead of Serializers.
You need to change from
class ArticleSerializer(serializers.ModelSerializer):
author = AuthorSerializer()
category = CategorySerializer()
class Meta:
model = Article
fields = '__all__'
to
class ArticleSerializer(serializers.ModelSerializer):
author = serializers.PrimaryKeyRelatedField()
category = serializers.PrimaryKeyRelatedField()
class Meta:
model = Article
fields = '__all__'
And check the documentation of PrimaryKeyRelatedField as it includes some different options that might be interesting for the design of your API
https://www.django-rest-framework.org/api-guide/relations/#primarykeyrelatedfield
Most likely you will need the read_only=True option so you don't need to override any method
Original answer with a bit of explanation:
You are getting the error because the POST is trying to create the nested objects but your serializer does not override the .create() method so the serializer does not know how to handle the nested relationships.
Take a look on https://www.django-rest-framework.org/api-guide/serializers/#writing-create-methods-for-nested-representations where you can get a grasp of what you need.
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'
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')
Post model
class Post(models.Model):
owner = models.ForeignKey(Profile, on_delete=models.CASCADE) # Profile is another model
title = models.CharField(max_length=300)
content = models.CharField(max_length=1000)
votes = models.IntegerField()
created_at = models.DateTimeField(auto_now_add=True)
updated_at = models.DateTimeField(auto_now=True)
subreddit = models.ForeignKey(Subreddit, on_delete=models.CASCADE) # Subreddit is another model
PostSerializer
class PostSerializer(serializers.ModelSerializer):
class Meta:
model = Post
fields = '__all__'
depth = 1
ListPostsOfReddit
class ListPostsOfReddit(ListCreateAPIView):
serializer_class = PostSerializer
def get_queryset(self):
return Post.objects.filter(subreddit__name=self.kwargs['r_name'])
In the ListCreateAPIView of rest-framework, I am able to GET all the foreign key data. In the form that rest-framework provides, only the
Title
Content
Votes
are asked, I want the foreign key fields to be also asked as input. How do I achieve that?
Use Two serializers, and manage those in get_serializer() method.
class PostListSerializer(serializers.ModelSerializer):
class Meta:
model = Post
fields = '__all__'
depth = 1
class PostSerializer(serializers.ModelSerializer):
class Meta:
model = Post
fields = '__all__'
class ListPostsOfReddit(ListCreateAPIView):
def get_serializer_class(self):
if self.request.method == 'GET':
return PostListSerializer
return PostSerializer
def get_queryset(self):
return Post.objects.filter(subreddit__name=self.kwargs['r_name'])
Note: I didn't tested/verified the solution. Please let me know if any error occured