How to filter/hide fields in django rest framework HTML form using authenticated user

I created two models:

  1. parcel (package) model,
  2. 'shelf' model to which parcels can be assigned.
class Parcel(models.Model):
    owner = models.ForeignKey(get_user_model(), on_delete=models.PROTECT)
    name = models.CharField(max_length=100, blank=False)
    contents = models.TextField(blank=False, validators=[MaxLengthValidator(1500)])
    size = models.CharField(max_length=50, blank=True, validators=[package_size_validator])
    weight = models.PositiveIntegerField(blank=True, null=True)
    contact = models.CharField(max_length=50, blank=True)
    creation_date = models.DateTimeField(auto_now_add=True)
    last_modification = models.DateTimeField(auto_now=True)
    code = models.CharField(max_length=30, unique=True, blank=False)

    def __str__(self):
        return f'Parcel: {self.code}, {self.owner}, {self.name}'


class ParcelShelf(models.Model):
    owner = models.ForeignKey(get_user_model(), on_delete=models.PROTECT)
    name = models.CharField(max_length=100, blank=False)
    creation_date = models.DateTimeField(auto_now_add=True)
    last_modification = models.DateTimeField(auto_now=True)
    parcels = models.ManyToManyField('Parcel', blank=True, related_name='shelf_parcel')

    def __str__(self):
        return f'ParcelShelf: {self.owner}, {self.name}'

I came to a solution where the logged-in user can see only his packages and shelves. The problem I have is with the many-to-many relationship where parcels can be added to shelves. I want to come to a solution where the logged in user can add to the shelf only those parcels which he is the owner, creator. It will look better in pictures.

All packages created by user t2@t2.com (user id = 17): parcels list

Now the view when the user t2@t2.com wants to create a shelf: shelf list All packages are visible, while only those created by the user t2@t2.com should be available. Code to serializer:

class ParcelShelfSerializer(serializers.ModelSerializer):
    owner = serializers.ReadOnlyField(source='owner.email')

    parcels = serializers.HyperlinkedRelatedField(many=True, read_only=False, view_name='parcels_detail_view',
                                                  # queryset=Parcel.objects.filter(owner=17)
                                                  queryset=Parcel.objects.all()
                                                  )

    class Meta:
        model = ParcelShelf
        fields = ('id', 'owner', 'name', 'creation_date', 'last_modification', 'parcels')

Below is a picture where only packages for a given, logged-in user are available: shelf list

Code to serializer:

class ParcelShelfSerializer(serializers.ModelSerializer):
    owner = serializers.ReadOnlyField(source='owner.email')

    parcels = serializers.HyperlinkedRelatedField(many=True, read_only=False, view_name='parcels_detail_view',
                                                  queryset=Parcel.objects.filter(owner=17)
                                                  # queryset=Parcel.objects.all()
                                                  )

    class Meta:
        model = ParcelShelf
        fields = ('id', 'owner', 'name', 'creation_date', 'last_modification', 'parcels')

I got to the point where the 'solution' is in the 'queryset' argument.

All users: queryset=Parcel.objects.all() Logged in user: queryset=Parcel.objects.filter(owner=17)

The problem is, this is hardcoded, and it should be something like: (owner=request.user). Unfortunately, I don't know how to achieve this in the serializer. I looked through other similar topics, but I didn't find a solution how to use the request method in the serializer field.

In addition, code in views:

class ParcelsShelfList(generics.ListCreateAPIView):
    # queryset = ParcelShelf.objects.all()
    serializer_class = ParcelShelfSerializer

    def get_queryset(self):
        user = self.request.user
        if bool(user and user.is_staff and user.is_admin):
            return ParcelShelf.objects.all()
        else:
            return ParcelShelf.objects.filter(owner=user)

    def perform_create(self, serializer):
        serializer.save(owner=self.request.user)
Back to Top