ОТПРАВЛЯЙТЕ данные только в том случае, если вы прошли проверку подлинности, и только своему пользователю, использующему django-rest-framework

#django #django-rest-framework

#джанго #django-rest-фреймворк #django #django-rest-framework

Вопрос:

я новичок в Django, поэтому извините, если это кажется глупым. я хочу добавить элемент в базу данных, только если пользователь аутентифицирован.

вот модели:

 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}' 
  

сериализаторы:

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


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

  

URL-адреса:

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

]
  

и, наконец, API

 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)
  

итак, проблема в том, что когда я отправляю сообщение в ‘api / salehistory’, я могу добавлять контент любому пользователю не только как аутентифицированный пользователь.
(используя knox authtoken для аутентификации).

Скажем, например, я аутентифицирован как пользователь1, и у меня есть свой токен аутентификации. Теперь я могу использовать этот токен для добавления элементов в модель SaleHistory для любого пользователя, что очень нежелательно.

как я могу это решить?

еще раз извините за грубое описание. впервые задаю вопрос здесь.

Комментарии:

1. Почему вы используете viewet вместо apiview?

2. Я не эксперт, но я думаю, что вы можете создать perform_create функцию типа get_queryset и убедиться в этой функции, что созданная история продаж принадлежит аутентифицированному пользователю.

3. честно говоря, я не знаю. Но то, что я понял из viewsets, позволяет упростить URL conf или что-то в этом роде. должен ли я использовать apiview?.

Ответ №1:

Сначала установите для user поля значение только для чтения, используя read_only_fields параметр meta

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

Теперь SaleHistorySerializier не будет принимать данные из user поля.

Затем вам необходимо переопределить perform_create(...) метод SaleHistoryViewSet класса

 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)