0

I want to set user_id field using JWT token and store in database table when new reservation is created. there can be single or multiple reservation request. whenever user create reservation i want to store there user_id in our table. currently there is no foreign key associated with it. it is simply an integer field.

I am able to fetch user_id from JWT.but its not updating in database

I know this question had been asked previously i tried all the answer of previous post but its not working for me. i dont know why

model.py

class reservations(models.Model):
  pet_id=models.IntegerField()
  user_id=models.IntegerField(default=0)
  location=models.PositiveSmallIntegerField()
  arrival=models.DateTimeField()
  depature=models.DateTimeField()
  comments=models.TextField(max_length=200)

view.py

class requestReservation(CreateAPIView):
  serializer_class = requestReservationSerailizer
  permission_classes = [IsAuthenticated]

  def create(self, request, *args, **kwargs):   
    serializer = requestReservationSerailizer(data=request.data,context={'user_id': request.user.id}, many=True)

    if not serializer.is_valid(raise_exception=False):
        return Response(serializer.errors, status=status.HTTP_400_BAD_REQUEST)


    self.perform_create(serializer)
    headers = self.get_success_headers(serializer.data)
    return Response({"message":"Success","status_message":"Reservation Created Successfully"},status=status.HTTP_200_OK)

serializer.py

class requestReservationSerailizer(ModelSerializer):
  user_id = SerializerMethodField('set_user_id')
  class Meta:
    model=reservations
    fields = [
        'pet_id',
        'user_id',
        'location',
        'arrival',
        'depature',                 
        'comments',
    ]

  def set_user_id(self, obj):
    obj.user_id = self.context.get("user_id")
    return obj.user_id

currently it is simply storing user_id as 0 which is default set in model.

Vallabh
  • 93
  • 2
  • 14

1 Answers1

0

SerializerMethodField is read-only by default, here's a quick look at the source code:

def __init__(self, method_name=None, **kwargs):
    self.method_name = method_name
    kwargs['source'] = '*'
    kwargs['read_only'] = True
    super(SerializerMethodField, self).__init__(**kwargs)

Assuming you want to read and write into this field; remove the SerializerMethodField overriding from the serializer declaration; and set the user_id in your view

class requestReservationSerailizer(ModelSerializer):
  class Meta:
    model=reservations
    fields = [
        'pet_id',
        'user_id',
        'location',
        'arrival',
        'depature',                 
        'comments',
    ]


  def create(self, request, *args, **kwargs):
    data = request.data.copy()
    for datum in data:
         datum['user_id'] = request.user.id

    serializer = requestReservationSerailizer(data=data, many=True)

    if not serializer.is_valid(raise_exception=False):
        return Response(serializer.errors, status=status.HTTP_400_BAD_REQUEST)


    self.perform_create(serializer)
    headers = self.get_success_headers(serializer.data)
    return Response({"message":"Success","status_message":"Reservation Created Successfully"},status=status.HTTP_200_OK)

Ofcourse; if you don't want your view to be doing this (and I'd agree with you here), then pass it in context (explicit) or use self.request.user.id and override validate_user_id

class requestReservationSerailizer(ModelSerializer):
  class Meta:
    model=reservations
    fields = [
        'pet_id',
        'user_id',
        'location',
        'arrival',
        'depature',                 
        'comments',
    ]

def validate_user_id(self, value):
    user_id = self.context.get('user_id', None)  # Assuming you continue to pass it in context
    if user_id is None:
        # Handle error
    return user_id
    # You can also do this; might raise an AttributeError if the user is not authenticated:
    # return self.request.user.id
rtindru
  • 5,107
  • 9
  • 41
  • 59
  • Thanks for your reply.. I am getting invalid syntax error on this line [x['user_id'] = request.user.id for x in data] – Vallabh May 14 '18 at 15:34
  • My bad; updated. Forgot that I can't do assignments inside list comprehensions: https://stackoverflow.com/questions/10291997/how-can-i-do-assignments-in-a-list-comprehension – rtindru May 14 '18 at 15:37
  • Thanks you so much for your help.. I was heating my head full day on this..haha – Vallabh May 14 '18 at 15:45
  • Happy to help :) – rtindru May 14 '18 at 15:59