Robins
Robins

Reputation: 45

POST data only if you are authenticated and only to your user using django-rest-framework

i'm new to Django so sorry if this seems stupid. i want to add an item to a database only if the user is authenticated .

here are the models:

class SaleItems(models.Model):
    product_name = models.CharField(max_length=50)
    price = models.IntegerField()
    product_type = models.CharField(max_length=25)
    description = models.CharField(max_length=250 ,default='', blank=True)
    brand = models.CharField(max_length=25, null=True,blank=True)
    image_path = models.ImageField(upload_to='images/product_image')
    date_added = models.DateField(auto_now_add=True)
    in_stock = models.BooleanField(default=True)

    def __str__(self):
        return f"{self.product_name}, price={self.price}"


class SaleHistory(models.Model):
    user = models.ForeignKey(User, on_delete=models.CASCADE)
    product = models.ForeignKey(SaleItems, on_delete=models.RESTRICT, default=None)
    date_bought = models.DateTimeField(auto_now_add=True)

    def __str__(self):
        return f'{self.date_bought}, {self.product}, {self.user}' 

the serializers:

class SaleItemSerializer(serializers.ModelSerializer):
    class Meta:
        model = SaleItems
        fields = '__all__'


class SaleHistorySerializier(serializers.ModelSerializer):
    class Meta:
        model = SaleHistory
        fields = '__all__'

urls:

routes = routers.DefaultRouter()
routes.register('api/saleitems', SaleItemViewSet, basename='saleitem')
routes.register('api/salehistory', SaleHistoryViewSet, basename='salehistory')
urlpatterns = [ path('',include(routes.urls))

]

and finally the apis

class SaleItemViewSet(viewsets.ModelViewSet):
    queryset = SaleItems.objects.all()
    permission_classes = [permissions.AllowAny]
    serializer_class = SaleItemSerializer


class SaleHistoryViewSet(viewsets.ModelViewSet):
    # queryset = SaleHistory.objects.all()
    permission_classes = [permissions.IsAuthenticated]
    serializer_class = SaleHistorySerializier

    def get_queryset(self):
        user = self.request.user
        return SaleHistory.objects.filter(user = user)

so the problem, when i post to 'api/salehistory' i am able to add content to any user not only as the authenticated user. (using knox authtoken for authentication).

Say for example i am authenticated as user1 and i have my auth token. Now I can use that token to add items to the SaleHistory model for any user which is very much undesired.

how can i solve this?

once again sorry for the crude description. first time asking question here.

Upvotes: 4

Views: 1046

Answers (1)

JPG
JPG

Reputation: 88549

First, set the user field as read_only by using read_only_fields meta option

class SaleHistorySerializier(serializers.ModelSerializer):
    class Meta:
        model = SaleHistory
        fields = '__all__'
        read_only_fields = ("user",)

Now, the SaleHistorySerializier will not accept the data from the user field.

Then, You need to override the perform_create(...) method of the SaleHistoryViewSet class

class SaleHistoryViewSet(viewsets.ModelViewSet):
    # queryset = SaleHistory.objects.all()
    permission_classes = [permissions.IsAuthenticated]
    serializer_class = SaleHistorySerializier

    def get_queryset(self):
        return SaleHistory.objects.filter(user=self.request.user)

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

Upvotes: 5

Related Questions