0

I have an api where users can create different objects. If the user is part of the staff, he can create the object with all the values he wants. However, if the user is not part of the staff, I want to force the value of a particular field.

I added the following code to a viewset that works well:

    @swagger_auto_schema(responses={201: CategoryProductSerializer})
    def create(self, request, *args, **kwargs):
        if not self.request.user.is_staff:
            request.data['client']=request.user.profil.client.pk
        print(request.data)
        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=status.HTTP_201_CREATED, headers=headers)

    def perform_create(self, serializer):
        serializer.save() 

How can I "generalize" this to all my modelviewsets? The important part of this create that must be common to all my viewsets is :

if not self.request.user.is_staff:
   request.data['client']=request.user.profil.client.pk
darkvodka
  • 303
  • 1
  • 3
  • 11

2 Answers2

0

Add the user to the context like this

serializer = self.get_serializer(data=request.data, context={"user": request.user})

then use the serializers validate or validate_client method to perform your checking

if not self.context['user'].is_staff:
    pass
Phteven
  • 400
  • 2
  • 7
0

Since the question is basically "How to generalize". I think you should create your own middleware.

class SimpleMiddleware:
    def __init__(self, get_response):
        self.get_response = get_response
        # One-time configuration and initialization.

    def __call__(self, request):
        # Code to be executed for each request before
        # the view (and later middleware) are called.

        response = self.get_response(request)

        # Code to be executed for each request/response after
        # the view is called.
        return response

    def process_view(self,request,view_func,*view_args,**view_kwargs):
           if not request.user.is_staff:
               request.client=request.user.profil.client.pk

Make sure you include your middleware in your MIDDLEWARE block of settings.py. ALso make sure you add it AFTER the AuthenticationMiddleware.

Mazhar Ali
  • 328
  • 1
  • 3
  • 13
  • Hello, when I add the middleware `response['client']` is always not defined. – darkvodka Nov 09 '21 at 10:39
  • @darkvodka Yeah sorry. My prev comment was based off from documentation. You need to override the function 'process_view'. Answer updated. If it still doesn't work, come back. – Mazhar Ali Nov 09 '21 at 12:20
  • it doesn't work. In process_view, request.user is always AnonymousUser. However, my middleware is the last in the list in my settings.py – darkvodka Nov 09 '21 at 12:58
  • I was able to authenticate in the middleware. However, `AttributeError: This QueryDict instance is immutable` it seems that you can't modify the query at this level. – darkvodka Nov 10 '21 at 09:41
  • data._mutable=True After you are done assigning the user. data._mutable=False – Mazhar Ali Nov 11 '21 at 08:10
  • I already tried this method. But I have another issue. `detail "CSRF Failed: CSRF cookie not set."` – darkvodka Nov 12 '21 at 15:54
  • Add another question for that. Or search for it. That's a different issue. – Mazhar Ali Nov 15 '21 at 05:24