Allow partial update in serializer_class in Django REST - django

I am trying to partially update my ProfileSerializer when i am making PATCH request. However i am not able to make it beacuse by default Serializer doesn't allow partial changes to be made. I am using Django Rest Framwork UpdateModelMixin to handle my patch request. Where can i set partial=True in my case?
View:
class ProfileViewPartialUpdate(GenericAPIView, UpdateModelMixin):
queryset = Profile.objects.all()
serializer_class = ProfileSerializer
lookup_field = 'token'
lookup_url_kwarg = 'pk'
def patch(self, request, *args, **kwargs):
return self.partial_update(request, *args, **kwargs)
Serializer:
class ProfileSerializer(serializers.ModelSerializer):
class Meta:
model = Profile
fields = ('token', 'bio', 'name', 'email', 'sport', 'location', 'image')

View:
from rest_framework import generics
class ProfileViewPartialUpdate(generics.RetrieveUpdateAPIView):
queryset = Profile.objects.all()
serializer_class = ProfileSerializer
lookup_field = 'pk'
Serializer:
class ProfileSerializer(serializers.ModelSerializer):
class Meta:
model = Profile
fields = ('token', 'bio', 'name', 'email', 'sport', 'location', 'image')

Look at this snippet code from one of my projects. You can modify accordingly. Add this to ProfileViewPartialUpdate class instead of patch.
def partial_update(self, request, slug):
user = self.request.user
get_blog = Blog.objects.get(slug=slug)
instance = self.get_object()
serializer = BlogSerializer(instance, data=request.data)
if serializer.is_valid():
serializer.save()
return Response(data=serializer.data, status=HTTP_201_CREATED)
return Response(data="wrong parameters", status=HTTP_400_BAD_REQUEST)
Hope this might help

Related

CurrentUserDefault doesn't work using Django Rest

I'm working with Django / Django Rest Framework and I'm looking for a solution to insert the logged user id automatically.
i tried to use, user = serializers.HiddenField(default=serializers.CurrentUserDefault()) :
But i doesn't work
This is my serializer class
from rest_framework import serializers
from contact.models import Contact
class ContactSerializer(serializers.ModelSerializer):
user = serializers.HiddenField(default=serializers.CurrentUserDefault())
class Meta:
model = Contact
fields = '__all__'
My View :
class ContactView(ListModelMixin, viewsets.GenericViewSet):
queryset = Contact.objects.all()
serializer_class = ContactSerializer
def create(self, request):
serializeObject = ContactSerializer(data = request.data, many=True)
if serializeObject.is_valid():
serializeObject.save()
contactObject = Contact.objects.all()
contactSerializer = ContactSerializer(contactObject, many=True)
return Response(contactSerializer.data, status = status.HTTP_201_CREATED)
return Response(serializeObject.errors, status.HTTP_400_BAD_REQUEST)
When you use CurrentUserDefault you need to pass the request in the context to your serializer as that is where the serializer will get the current user from. See Including extra context [DRF docs]:
class ContactView(ListModelMixin, viewsets.GenericViewSet):
queryset = Contact.objects.all()
serializer_class = ContactSerializer
def create(self, request):
serializeObject = ContactSerializer(data = request.data, many=True, context={'request': request})
...

How to use hyperlinkedModelSerializer in django rest framework

How to use hyperlinkedModelSerializer in django rest framework My output shows:
HyperlinkedRelatedField requires the request in the serializer context. Add context={'request': request} when instantiating the serializer.
The code is given below:
serailizers.py
#Program Serializer
class ProgramSerializer(serializers.ModelSerializer):
class Meta:
model = Program
fields = '__all__'
#Program MiniSerializer
class ProgramMiniSerializer(serializers.HyperlinkedModelSerializer):
programCode = serializers.HyperlinkedRelatedField(many=True,view_name='program-detail', read_only=True)
class Meta:
model = Program
fields = ('programCode', 'pro_name', 'url', 'DepartmentID')
viewsets.py
class ProgramViewSet(viewsets.ModelViewSet):
queryset = Program.objects.all()
serializer_class = ProgramSerializer
filterset_class = ProgramFilter
filter_backends = (django_filters.rest_framework.DjangoFilterBackend,)
__basic_fields = ( 'programCode', 'pro_name','pro_shortForm', 'DepartmentID')
filter_backends = (filters.DjangoFilterBackend, SearchFilter, OrderingFilter)
filter_fields = ('programCode', 'DepartmentID')
search_fields = ('DepartmentID')
def list(self, request, *args, **kwargs):
programs = Program.objects.all()
serializer = ProgramMiniSerializer(programs, many=True)
return Response(serializer.data)
def get_queryset(self):
programs = Program.objects.all()
return programs
def retrieve(self, request, *args, **kwargs):
params=kwargs
print(params['pk'])
# programs = Program.objects.all()
programs = Program.objects.filter(DepartmentID = params['pk'])
serializer = ProgramMiniSerializer(programs, many=True)
return Response(serializer.data)
In list and retrieve methods where you initialize serializer, you need to pass context to it, like this:
serializer = ProgramMiniSerializer(
programs,
many=True,
context={
'request': request,
},
)

DRF how to update email with #action?

When I try to update my authenticated user but it's create new user. Where is problem?
View
class UserViewSet(mixins.RetrieveModelMixin,
mixins.UpdateModelMixin,
mixins.DestroyModelMixin,
viewsets.GenericViewSet):
permission_classes = (IsAuthenticated,)
serializer_class = UserSerializer
def get_object(self):
return self.request.user
Action
#action(methods=['PATCH'], detail=False)
def change_email(self, *args, **kwargs):
user = self.get_object()
serializer = serializers.UserEmailSerializer(data=self.request.data, context={'request': self.request})
serializer.is_valid(raise_exception=True)
serializer.save()
self.send_email(user.email)
return Response({'Confirm yours new email'}, status=status.HTTP_200_OK)
Serilializer for action
class UserEmailSerializer(serializers.ModelSerializer):
class Meta:
model = User
fields = ('id', 'email')
read_only_fields = ('id',)

Bad request 400 while trying to do partial update with UpdateAPIView

I am using DRF UpdateAPIView to take in PATCH method and partially update my model. It should by default handel correctly partial update but i somehow get Bad request error. What could be issue here?
View:
class ProfileViewUpdate(generics.UpdateAPIView):
queryset = Profile.objects.all()
serializer_class = ProfileSerializer
lookup_field = 'token'
lookup_url_kwarg = 'pk'
def partial_update(self, request, *args, **kwargs):
kwargs['partial'] = True
return self.update(request, *args, **kwargs)
Serializer:
class ProfileSerializer(serializers.ModelSerializer):
class Meta:
model = Profile
fields = ('token', 'bio', 'name', 'email', 'sport', 'location', 'image')

No PUT method in DRF using ModelViewset

I am using Django 2.2 with Django Rest Framework 3.7.
I have a class like this:
class UserViewSet(viewsets.ModelViewSet):
permission_classes = [AllowAny]
serializer_class = UserSerializer
queryset = User.objects.all()
def update(self, request, *args, **kwargs):
import pdb;pdb.set_trace()
I've created UserSerializer like this:
class UserSerializer(serializers.ModelSerializer):
class Meta:
model = User
fields = ('id', 'email', 'name', 'password')
write_only_fields = ('password',)
read_only_fields = ('id',)
def create(self, validated_data):
user = User.objects.create(
email=validated_data['email'],
name=validated_data['name'],
)
user.set_password(validated_data['password'])
user.save()
return user
def update(self, instance, validated_data):
print('lalala from serialzier')
import pdb;pdb.set_trace()
instance.username = validated_data['username']
instance.save()
return instance
Only allowed methods being shown are - Allow: GET, POST, HEAD, OPTIONS
I wonder why I am unable to perform actions like PUT, DELETE, RETRIEVE. These are by default supported by using ModelViewset as per documentation.
In shown code neither serializer's update() nor views.py update() method getting called. Any hint would be appreciated.
Does this answer your question?
class UserViewSet(viewsets.ModelViewSet):
permission_classes = [AllowAny]
serializer_class = UserSerializer
queryset = User.objects.all()
def put(self, request, id, format=None):
...
def delete(self, request, id, format=None):
...