Reputation: 402
I want that any user could create their own products with my RESTful API. For this purpose, I created a view that inherits ListCreateAPIView. The problem is that a user should only create products that he/she own, so when the instance of the Product model is created, I wanted that the field Owner corresponds to the user that is authenticated.
Here's my Product model
class Product(models.Model):
owner = models.ForeignKey(User)
name = models.CharField(max_length=30)
Obviously my serializer is:
class ProductSerializer(serializers.ModelSerializer):
class Meta:
model = models.Product
and my view:
class ProductView(generics.ListCreateAPIView):
queryset = models.Product.objects.all()
serializer_class = serializers.ProductSerializer
permission_classes = (IsAuthenticatedOrReadOnly,)
def create(self, request, *args, **kwargs):
serializer = self.get_serializer(data=request.data)
serializer.is_valid(raise_exception=True)
#serializer.initial_data['owners'] = models.Person.objects.get(user__email=request.user).user_id
self.perform_create(serializer)
headers = self.get_success_headers(serializer.data)
return Response(serializer.data, status=status.HTTP_201_CREATED, headers=headers)
As you can see, I tried modifying the "initial_data", but it is a QueryDict, which is inmutable. Another option is transforming it into a Python dict and then adding the "owner" value, but at doing that I get every value as a list (i.e. {'name': ['MyName']}), so it would be a very ugly way to solve the problem, I think it should be a more straightforward solution.
Upvotes: 10
Views: 8587
Reputation: 4667
You can pass initial data in view and then rewrite default value in serializer
views.py
class ItemListCreateView(ListCreateAPIView):
def get_serializer_context(self):
return {"delivery_request": self.kwargs['req_pk']}
serializers.py
class ItemCreateSerializer(ModelSerializer):
delivery_request = CharField(default='')
def validate_delivery_request(self, value):
try:
value = DeliveryRequest.objects.get(
id=self.context["delivery_request"])
except DeliveryRequest.DoesNotExist:
raise ValidationError(
self.Meta.error_messages['delivery_request_not_found'])
return value
PS. it is useful when you want to populate not Null data from url for example
Upvotes: 1
Reputation: 667
Simple solution below. owner
will not be visible in request GET/POST/PUT etc. but will be auto assigned to current authenticated user.
from rest_framework.serializers import (CurrentUserDefault, HiddenField,
ModelSerializer)
class ProductSerializer(ModelSerializer):
owner = HiddenField(default=CurrentUserDefault())
class Meta:
model = models.Product
Upvotes: 1
Reputation: 47856
You can override perform_create()
and pass the current user as the owner
. Then, when the Product
instance will be created, owner
field will be saved with the current user value.
class ProductView(generics.ListCreateAPIView):
queryset = models.Product.objects.all()
serializer_class = serializers.ProductSerializer
permission_classes = (IsAuthenticatedOrReadOnly,)
def perform_create(self, serializer):
serializer.save(owner=self.request.user) # pass the current user as the 'owner'
Also, you should define owner
field in your serializer as read_only
. Then the field will not be required during deserialization. But, this field will be included in the output on serialization.
class ProductSerializer(serializers.ModelSerializer):
class Meta:
model = models.Product
extra_kwargs = {'owner': {'read_only':True}} # set 'owner' as read-only field
Upvotes: 11