Drf: serializers.ModelField > How can i get user_id appropriately?

I want to implement the 'user_id' to be automatically saved at the backend without receiving it from the client. (when create object!) This is my code.

models.py

class User(AbstractUser):
    username = None
    email = models.EmailField(max_length=255, unique=True)
    
    USERNAME_FIELD = 'email'
    REQUIRED_FIELDS = []
    
    objects = UserManager()
    social_profile = models.URLField(null=True,blank=True)
    realname = models.CharField(max_length=50, blank=True)
    nickname = models.CharField(max_length=50, null=True, unique=True) 
    address = models.CharField(max_length=200, blank=True)
    phone = models.CharField(max_length=100, blank=True)

    def __str__(self):
        return self.email

class Item(models.Model):
    user_id = models.ForeignKey(User, related_name='item_sets', on_delete=models.CASCADE)
    category_id = models.ForeignKey(Category, related_name='item_sets', on_delete=models.DO_NOTHING)
    description = models.TextField()
    feature = models.TextField()
    product_defect = models.TextField()
    size = models.CharField(max_length=6)
    height = models.DecimalField(max_digits=4, decimal_places=1, default=0)
    weight = models.DecimalField(max_digits=4, decimal_places=1, default=0)
    condition = models.CharField(max_length=20)
    price = models.IntegerField()
    created_at = models.DateTimeField(auto_now_add=True)
    updated_at = models.DateTimeField(auto_now=True)
    sold_out = models.BooleanField(default=False)

    def __str__(self):
        return self.description
view.py

class ItemViewSet(ModelViewSet):
    queryset = Item.objects.all()
    serializer_class = ItemSerializer
    filter_backends = [SearchFilter, OrderingFilter]
    search_fields = ['description']    # ?search=
    ordering_fields = ['created_at']  # ?ordering=
    ordering = ['-created_at']
    authentication_classes = (JWTCookieAuthentication,)

    # create
    def create(self, request, *args, **kwargs):
        city = request.data['city']
        gu = request.data['gu']
        dong = request.data['dong']
        if city is not None and gu is not None and dong is not None:
            location = Location.objects.get(
                Q(city=city) & Q(gu=gu) & Q(dong=dong)
            )
        else:
            return Response(
                {"message": "주소정보를 모두 입력해주세요."},
                status=status.HTTP_400_BAD_REQUEST
            )
        serializer = self.get_serializer(data=request.data)
        serializer.is_valid(raise_exception=True)
        self.perform_create(serializer)
        new_item = Item.objects.get(id=serializer.data['id'])
        headers = self.get_success_headers(serializer.data)
        LocationSet.objects.create(item_id=new_item, location_id=location)
        return Response(serializer.data, status=status.HTTP_201_CREATED, headers=headers)

    # here!
    def perform_create(self, serializer):
        serializer.save(user_id=self.request.user)
serializers.py

class ItemSerializer(serializers.ModelSerializer):
    photos = PhotoSerializer(source='photo_sets', many=True, read_only=True)
    style_photos = StylePhotoSerializer(source='style_photo_sets', many=True, read_only=True)
    user_id = serializers.ModelField(model_field=User()._meta.get_field('id'), required=False) #here!

    class Meta:
        model = Item
        fields = '__all__'

    # Photo, StylePhoto
    def create(self, validated_data):
        images_data = self.context['request'].FILES
        item = Item.objects.create(**validated_data)
        for photo_data in images_data.getlist('photos_data'):
            Photo.objects.create(item_id=item, photo=photo_data)
        for style_photo_data in images_data.getlist('style_photos_data'):
            StylePhoto.objects.create(item_id=item, user_id=self.context['request'].user,
                                      photo=style_photo_data)
        print(User()._meta.get_field('id'))
        return item

so I overrided perform_create() in views.py and write 'user_id = serializers.ModelField(model_field=User()._meta.get_field('id'), required=False)' in serializers.py but it doesn't work well like my intend... enter image description here

correct user_id is 8. but my object has 18..:< 18 is just item_id, not user_id.. what should I do to fix this error?

Try this:

views.py : use the perform_create() method to save the user_id.

Note: the user must be authenticated so that we can get them from the request.

class ItemViewSet(ModelViewSet):
    # your code ...

    # create
    def create(self, request, *args, **kwargs):
        # your code code ...

    def perform_create(self, serializer):       # new
        serializer.save(user_id=self.request.user)

serializers.py : Get the user_id from the database and make it readonly as it is not supposed to be edited by the user:

class ItemSerializer(serializers.ModelSerializer):
    # your code ..
    user_id = serializers.ReadOnlyField(source='user_id.id')   # new

    class Meta:
        model = Item
        fields = '__all__'

    # Photo, StylePhoto
    def create(self, validated_data):
        images_data = self.context['request'].FILES
        item = Item.objects.create(**validated_data)
        for photo_data in images_data.getlist('photos_data'):
            Photo.objects.create(item_id=item, photo=photo_data)
        for style_photo_data in images_data.getlist('style_photos_data'):
            StylePhoto.objects.create(item_id=item,photo=style_photo_data)   # new
        print(User()._meta.get_field('id'))
        return item

I would also recommend you change the user_id field to something like owner to prevent future confusion.

Back to Top