I have a model of uploads and i want to associate the uploaded images to the user so that later each user can only view his objects so so i m trying to save the created objects to the authenticated user, but it's not working and i keep getting owner =null on my model
#api_view(['GET', 'POST'])
def Upload_list(request):
if request.method == 'GET':
queryset = Uploads.objects.all()
uploads=queryset.filter(owner=request.user)
serializer = UploadSerializer(uploads, many=True)
return Response(serializer.data)
elif request.method == 'POST':
serializer = UploadSerializer(data=request.data)
if serializer.is_valid():
serializer.save(owner=request.user)
respFile=list(File.objects.filter(id=str(File.objects.latest('created_at'))))
return Response(respFile)
return Response(serializer.errors, status=status.HTTP_400_BAD_REQUEST)
Edit : i think the problem is in the Post request itself it is not overriding the default method therefore the changes i apply do not work any idea how to change the post method ?
try this
class IsOwnerFilterBackend(filters.BaseFilterBackend):
def filter_queryset(self, request, queryset, view):
queryset=Uploads.objects.all()
return queryset.filter(owner=request.user)
class UploadView(viewsets.ModelViewSet):
queryset=Uploads.objects.all()
serializer_class=UploadSerializer
filter_backends = (IsOwnerFilterBackend,)
#api_view(['GET', 'POST'])
def methodes(self,request,*args,**kwargs):
if request.method=='POST':
serializer=UploadSerializer(data=request.data)
if serializer.is_valid():
serializer.save(owner=request.user)
return Response("test_token success", status=status.HTTP_200_OK)
return HttpResponse({'message':'error'},status=400)
elif request.method=='GET':
images=Uploads.objects.filter(owner=request.user)
serializers=UploadSerializer(images[0],many=False)
return JsonResponse(serializers.data,safe=False)
Related
Creating a custom permission to ensure only the user who owns an instance of the user object can update it like so
class UserUpdatePermission(BasePermission):
message = 'only users can edit their profile'
def has_permission(self, request, view):
return request.user.is_authenticated
def has_object_permission(self, request, view, obj):
if request.method in SAFE_METHODS:
return True
request.user == User.objects.get(username=view.kwargs['username'])
#api_view(['POST'])
#permission_classes([UserUpdatePermission])
#parser_classes([FormParser, MultiPartParser])
def UpdateUserProfile(request, username):
user = User.objects.get(username=username)
serializer = UpdateUserSerializer(instance=user, data=request.data)
if serializer.is_valid(raise_exception=True):
serializer.save()
return Response(serializer.data)
From inserting print statements around the code, i noticed the has_permission function in the class is being called but not the has_object_permission function. So, the object level permission isn't working. What am i getting wrong here?
this is my modelViewSet
class UserViewSet(viewsets.ModelViewSet):
def list(self, request):
users = User.objects.all()
serializer = UserSerializer(users, many=True)
return Response(serializer.data, status=status.HTTP_200_OK)
def create(self, request):
serializer = UserSerializer(data=request.data)
if serializer.is_valid(raise_exception=True):
pass
def retrieve(self, request, pk):
user = get_object_or_404(User, pk=pk)
serializer = UserSerializer(user)
return Response(serializer.data, status=status.HTTP_200_OK)
def get_permissions(self):
if self.action == "list":
permission_classes = [
IsAdminUser,
]
elif self.action == "create":
permission_classes = [AllowAny]
else:
permission_classes = [AccountOwnerPermission]
return [permission() for permission in permission_classes]
and this is the custom permission class
class AccountOwnerPermission(permissions.BasePermission):
def has_object_permission(self, request, view, obj):
print(object)
print(request.user)
return obj == request.user
i access this view from another user and it show me user retrieve, and that 2 prints on
AccountOwnerPermission won't run. can someone tell me what is wrong with what i did and why has_object_permission wont run.
i change has_object_permission to has_permission and it works, but i dont have access to obj on the other hand
From the docs:
If you're writing your own views and want to enforce object level permissions, or if you override the get_object method on a generic view, then you'll need to explicitly call the .check_object_permissions(request, obj) method on the view at the point at which you've retrieved the object.
So you'll need to call check_object_permissions in your retrieve to be able to trigger has_object_permission:
def retrieve(self, request, pk):
user = get_object_or_404(User, pk=pk)
self.check_object_permissions(request, user) # Add this line
serializer = UserSerializer(user)
return Response(serializer.data, status=status.HTTP_200_OK)
I am trying to make the PUT and DELETE methods require authentication but I want the GET method to be public. I know I can take the GET method out and put it into its own function but I would need to make another url for it. What would be the best way to approach this? thanks
#api_view(['GET', 'PUT', 'DELETE'])
#permission_classes([IsAuthenticated])
def getOrUpdateOrDeleteCar(request, pk):
if request.method == 'GET':
vehicle = Car.objects.get(id=pk)
serializer = CarSerializer(vehicle, many=False)
return Response(serializer.data)
elif request.method == 'PUT':
data = request.data
car = Car.objects.get(id=pk)
car.image=data['image']
car.make=data['make']
car.prototype=data['prototype']
car.year=data['year']
car.serviceInterval=data['serviceInterval']
car.seats=data['seats']
car.color=data['color']
car.vin=data['vin']
car.currentMileage=data['currentMileage']
car.save()
serializer = CarSerializer(car, many=False)
return Response(serializer.data)
elif request.method == 'DELETE':
car = Car.objects.get(id=pk)
car.delete()
return Response('Car Deleted!')
Write a custom permission class:
from rest_framework.permissions import BasePermission
class CarPermission(BasePermission):
def has_permission(self, request, view):
if request.method == 'GET':
return True
return bool(request.user and request.user.is_authenticated)
And use it in your API:
#api_view(['GET', 'PUT', 'DELETE'])
#permission_classes([CarPermission])
def getOrUpdateOrDeleteCar(request, pk):
...
How do I write the following views using class based view?
#api_view(['GET', 'POST'])
def hotel_list(request):
# List all hotel or add new .
if request.method == 'GET':
if request.user.is_authenticated:
# Allow GET request for all authenticated users
hotels = models.Hotel.objects.all()
serializer = serializers.HotelSerializer(hotels, many=True)
return Response(serializer.data)
return Response({"message": "not authorized"}, status=status.HTTP_401_UNAUTHORIZED)
elif request.method == 'POST':
if request.user.is_superuser:
# Allow POST method for super users only
serializer = serializers.HotelSerializer(data=request.data)
if serializer.is_valid():
serializer.save()
return Response(serializer.data, status=status.HTTP_201_CREATED)
else:
return Response(serializer.errors, status=status.HTTP_400_BAD_REQUEST)
return Response({"message": "not authorized"}, status=status.HTTP_401_UNAUTHORIZED)
I want to allow different permissions for different groups of user.
First create custom-permissions
permissions.py
class CreateAdminOnly(permissions.BasePermission):
def has_permission(self, request, view):
if request.method == 'POST':
return request.user.is_superuser
return request.user.is_authenticated
def has_object_permission(self, request, view, obj):
if request.method == 'POST':
return request.user.is_superuser
return request.user.is_authenticated
use it with modelviewset in views.py
from rest_framework import mixins
from rest_framework.permissions import IsAuthenticated
from .permissions import CreateAdminOnly
class CreateListRetrieveViewSet(mixins.CreateModelMixin,
mixins.ListModelMixin,
viewsets.GenericViewSet):
queryset = models.Hotel.objects.all()
serializer_class = HotelSerializer
permission_classes = [CreateAdminOnly]
I want to make sure the request.user can only issue a POST request to create a forum topic in which they are the auther. With PUT and DELETE I'm able to achieve that by using the has_object_permission but with POST I'm not able to do that, I'm guessing because the object hasn't been created yet.
class TopicPermission(IsAuthenticatedOrReadOnly):
"""
Any user should be able to read topics but only authenticated
users should be able to create new topics. An owner or moderator
should be able to update a discussion or delete.
"""
def has_object_permission(self, request, view, obj):
if request.method in SAFE_METHODS:
return True
# Instance must have an attribute named `author` or moderator
return obj.author == request.user or request.user.forum_moderator
How would I go about verifying request.user == obj.author in POST requests?
I ended up doing the validation in the viewset instead of the serializer:
class TopicViewSet(viewsets.ModelViewSet):
permission_classes = (TopicPermission, )
queryset = Topic.objects.all()
serializer_class = TopicSerializer
def create(self, request, *args, **kwargs):
"""
verify that the POST has the request user as the obj.author
"""
if request.data["author"] == str(request.user.id):
serializer = self.get_serializer(data=request.data)
serializer.is_valid(raise_exception=True)
self.perform_create(serializer)
headers = self.get_success_headers(serializer.data)
return Response(serializer.data, status=201, headers=headers)
else:
return Response(status=403)