No PUT method in DRF using ModelViewset - django

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):
...

Related

Django Rest-Framework-Simplejwt not working with modheader

I am working on some projects and trying to the list view of the book. I used Django Rest-Framework-Simplejwt to generate tokens and mod header for authentication. When I tried to request a token for a user such as the admin user, and enter it into the mod header, the request is still unauthorized. I tried to do it a couple of times, but still not working.
Views.py
from rest_framework import generics, permissions
from rest_framework.permissions import IsAuthenticated
from rest_framework.exceptions import ValidationError
from django.contrib.auth.models import User
from .models import Book
from .serializers import (
BookSerializer,
RegistrationSerializer
)
class BookCreateView(generics.CreateAPIView):
"""Create a Book"""
queryset = Book.objects.all()
serializer_class = BookSerializer
permission_classes = (IsAuthenticated,)
def perform_create(self, serializer):
serializer.save(user=self.request.user)
class BookListView(generics.ListAPIView):
"""Show all books"""
serializer_class = BookSerializer
permission_classes = (IsAuthenticated,)
def get_queryset(self):
user = self.request.user
return Book.objects.filter(user=user)
class BookDetailView(generics.RetrieveAPIView):
"""Show detail of the book"""
serializer_class = BookSerializer
permission_classes = (IsAuthenticated,)
def get_queryset(self):
user = self.request.user
return Book.objects.filter(user=user)
class BookUpdateView(generics.RetrieveUpdateDestroyAPIView):
"""update detail of the book"""
queryset = Book.objects.all()
serializer_class = BookSerializer
permission_classes = (IsAuthenticated,)
def delete(self, request, *args, **kwargs):
book = Book.objects.filter(user=self.request.user, pk=kwargs['pk'])
if book.exists():
return self.destroy(request, *args, **kwargs)
else:
raise ValidationError('Book is not yours!')
def perform_update(self, serializer, **kwargs):
book = Book.objects.get(pk=self.kwargs['pk'])
if self.request.user != book.user:
raise ValidationError("You are not the owner of this book")
serializer.save(user=self.request.user, book=book)
class UserRegistrationView(generics.CreateAPIView):
queryset = User.objects.all()
serializer_class = RegistrationSerializer
permission_classes = [permissions.AllowAny]
Serializers.py
from rest_framework import serializers
from django.contrib.auth.models import User
from .models import Book
class BookSerializer(serializers.ModelSerializer):
"""Serializer for Book"""
class Meta:
model = Book
fields = (
'id','user',
'title', 'author',
'description', 'image')
read_only_fields = ('id', 'user')
class RegistrationSerializer(serializers.ModelSerializer):
password = serializers.CharField(style={'input type':'password'}, write_only=True)
class Meta:
model = User
fields = ('username', 'email', 'password')
def create(self, validated_data):
user = User.objects.create(
username=validated_data['username'],
email=validated_data['email'])
user.set_password(validated_data['password'])
user.save()
return user
I entered the correct Token (copy&paste), but still not able to authenticate.
You are using "Token <eyJ..>". But instead your token should be like "Bearer <eyJ..>"
Some of Simple JWT’s behavior can be customized through settings variables in settings.py

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',)

Allow partial update in serializer_class in Django REST

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

POST http://127.0.0.1:8000/api/register/ 400 (Unauthorized)

view.py
class UserViewSet(viewsets.ModelViewSet):
""" API endpoint that allows users to be viewed or edited. """
serializer_class = UserSerializer
queryset = UserRegister.objects.all()
authentication_classes = (TokenAuthentication,)
permission_classes = (permissions.UpdateRegister,)
This is the view.py file. Here i have added authentication and permission to my view set.
permission.py
class UpdateRegister(permissions.BasePermission):
""" Allow user to edit their own profile. """
def has_object_permissions(self, request, view, obj):
""" Check user is trying to edit their own profile. """
if request.method in permissions.SAFE_METHODS:
return True
return obj.id == request.user.id
serializer.py
class UserSerializer(serializers.ModelSerializer):
class Meta:
model = UserRegister
fields = ('id', 'name', 'email', 'password')
extra_kwargs = {'password': {'write_only': True}}
def create(self, validated_data):
""" Create and return a new user"""
user = UserRegister(
email=validated_data['email'],
name=validated_data['name'],
)
user.set_password(validated_data['password'])
user.save()
return user
Error shown in network tab
So guy i am being bother by this error. Hope you guys will address my mistake and help me to solve the error.

django rest framework RetrieveUpdateAPIView

I come from Vietnam.
I want to update User by Django Rest FrameWork. I can update User by 'pk'. But I can't update User by 'username'. I hope that everyone help me. Thank you so much.
serializers.py
class UserDetailSerializer(serializers.ModelSerializer):
url_update = serializers.HyperlinkedIdentityField(view_name='api:UserUpdateAPIView', lookup_field='username')
class Meta:
model = User
fields = ('url_update', 'username', 'email', 'user_permissions', 'is_staff', 'groups', 'last_login')
class UserUpdateSerialier(serializers.ModelSerializer):
password = serializers.CharField(
style={'input_type': 'password'}
)
class Meta:
model = User
fields = ('pk', 'username', 'password')
def update(self, instance, validated_data):
instance.username = validated_data.get('username', instance.username)
instance.set_password(validated_data.get('password', instance.password))
instance.save()
return instance
views.py
class UserDetailAPIView(generics.RetrieveAPIView):
permission_classes = (permissions.IsAdminUser,)
serializer_class = UserDetailSerializer
#queryset = User.objects.all()
lookup_field = 'username'
def get_object(self):
username = self.kwargs["username"]
return get_object_or_404(User, username=username)
class UserUpdateAPIView(generics.RetrieveUpdateAPIView):
permission_classes = (permissions.IsAdminUser,)
#queryset = User.objects.all()
serializer_class = UserUpdateSerialier
def get_object(self):
username = self.kwargs["username"]
return get_object_or_404(User, username=username)
def put(self, request, *args, **kwargs):
return self.update(request, *args, **kwargs)
urls.py
url(r'^$', views.UserListAPIView.as_view(), name='UserListAPIView'),
url(r'^(?P<username>.*)/$', views.UserDetailAPIView.as_view(), name='UserDetailAPIView'),
url(r'^(?P<username>.*)/update/$', views.UserUpdateAPIView.as_view(), name='UserUpdateAPIView'),
HTTP 404 Not Found
Allow: GET, HEAD, OPTIONS
Content-Type: application/json
Vary: Accept
{
"detail": "Not found."
}
Try editing your view like this,
class UserUpdateAPIView(generics.RetrieveUpdateAPIView):
permission_classes = (permissions.IsAdminUser,)
serializer_class = UserUpdateSerialier
lookup_field = 'username'
def get_object(self):
username = self.kwargs["username"]
return get_object_or_404(User, username=username)
def put(self, request, *args, **kwargs):
return self.update(request, *args, **kwargs)
You need to set lookup_field = 'username' to the UserUpdateAPIView just like you did with the UserDetailAPIView