Reputation: 848
I am working with django rest framework. I have Product and Review models. Review is related to Product like so;
class Product(models.Model):
name = models.CharField(max_length=200, null=False, blank=False)
description = models.TextField(max_length=2000, null=False, blank=False)
owner = models.ForeignKey(User, on_delete=models.CASCADE)
slug = models.SlugField(unique=True)
category = models.ForeignKey(Category, on_delete=models.CASCADE)
is_featured = models.BooleanField(default=False)
created= models.DateTimeField(auto_now_add=True)
class Review(models.Model):
author = models.ForeignKey(User, on_delete=models.CASCADE)
product= models.ForeignKey(Product, on_delete=models.CASCADE)
title = models.CharField(max_length=80, blank=False, null=False)
body = models.TextField(max_length=400, blank=False, null=False)
is_approved = models.BooleanField(default=False)
created = models.DateTimeField(auto_now_add=True)
I wrote a serializer class for the review:
class ReviewSerializer(serializers.ModelSerializer):
author = UserSerializer(read_only=True)
class Meta:
model = Review
fields = ['id', 'author', 'title', 'body', 'is_approved', 'created']
def create(self, validated_data):
title = validated_data.get('title')
body = validated_data.get('body')
author = self.context['request'].user
review = Review.objects.create(title=title, body=body, author=author)
return review
and in my views.py, i have this;
class ReviewCreateView(CreateAPIView):
serializer_class = ReviewSerializer
queryset = Review.objects.all()
permission_classes = [IsAuthenticated,]
authentication_classes = [TokenAuthentication,]
def create(self, request, *args, **kwargs):
serializer = self.get_serializer(data=request.data)
serializer.is_valid(raise_exception=True)
product_id = kwargs.get('product')
product = Product.objects.get(id=product_id)
serializer.save(product=product)
headers = self.get_success_headers(serializer.data)
return Response(serializer.data, status=status.HTTP_201_CREATED, headers=headers)
in my urls urlpatterns:
path('api/review/new/<product>/', ReviewCreateView.as_view(), name="create-review"),
Issue is when i send a review from the frontend to that api, i keep getting a Not Null constraint error like so:
IntegrityError at /api/review/new/23/ NOT NULL constraint failed: products_review.product_id
I have handled the product saving inside the CreateAPIView in my views, but for some reasons Django isn't picking it. How do i make this work please? Any assistance will be appreciated. Please note that answers for similar questions i found here didn't work for me.
Upvotes: 0
Views: 361
Reputation: 887
You are almost right. You passed the product instance, so it should be included in the validated_data for the ReviewSerializer.create
method. But you don't use it when you are actually creating the review instance.
class ReviewSerializer(serializers.ModelSerializer):
author = UserSerializer(read_only=True)
class Meta:
model = Review
fields = ['id', 'author', 'title', 'body', 'is_approved', 'created']
def create(self, validated_data):
title = validated_data.get('title')
body = validated_data.get('body')
author = self.context['request'].user
product = validated_data.get('product')
review = Review.objects.create(
title=title,
body=body,
author=author,
product=product
)
return review
https://www.django-rest-framework.org/api-guide/serializers/#passing-additional-attributes-to-save
Also why can't you just have a product field on your review serializer?
Upvotes: 2