Как реализовать фильтрацию и базовую аутентификацию в django rest framework?
В своем проекте я использую django rest framework. Для фильтрации результатов я использую бэкенд django_filters. Вот мой код:
models.py
class Robot(models.Model):
robot = models.CharField(max_length=100)
short_Description = models.CharField(max_length=200)
status = models.CharField(max_length=20)
parameter = models.CharField(max_length=200)
jenkins_job = models.CharField(max_length=100, default='JenkinsJobName')
jenkins_token = models.CharField(max_length=100, default='JenkinsToken')
def __str__(self):
return self.robot
class assignParameter(models.Model):
parameterName = models.CharField(max_length=100, blank=True)
assignRobot= models.ForeignKey(Robot, on_delete=models.CASCADE, related_name='param', blank=True, null=True)
class jenkinsHistory(models.Model):
jenkinsJobName = models.ForeignKey(Robot, on_delete=models.CASCADE, related_name='JenkinJobName', blank=True, null=True)
jenkinsBuildNumber = models.CharField(max_length=100,blank=True)
jenkinsBuildStatus = models.CharField(max_length=200,blank=True)
errorMsg = models.CharField(max_length=500,blank=True)
Param = models.CharField(max_length=500,blank=True, null=True)
Serializers.py
from hello.models import Robot,assignParameter,jenkinsHistory
from rest_framework import serializers
class assignParameterSerializer(serializers.ModelSerializer):
class Meta:
model = assignParameter
fields = ['id', 'parameterName', 'assignRobot']
class jenkinsHistorySerializer(serializers.ModelSerializer):
jenkinsJobName = serializers.SlugRelatedField(read_only=True, slug_field='robot')
class Meta:
model = jenkinsHistory
# list_serializer_class = FilteredAssessmentsSerializer
fields = ['id','jenkinsJobName','jenkinsBuildNumber','jenkinsBuildStatus','errorMsg','Param']
class RobotSerializer(serializers.ModelSerializer):
param = assignParameterSerializer(many=True, read_only=True)
# JenkinJobName = jenkinsHistorySerializer(many=True, read_only=True)
class Meta:
model = Robot
fields = ['id', 'robot', 'short_Description', 'status', 'parameter', 'jenkins_job', 'jenkins_token', 'param']
и вот мой view.py:
from requests import api
from rest_framework import status
from rest_framework.decorators import api_view
from rest_framework.response import Response
from rest_framework.filters import SearchFilter
from django_filters.rest_framework import DjangoFilterBackend
from django_filters import rest_framework as filters
from hello.models import Robot,jenkinsHistory
from hello.api.serializers import RobotSerializer, jenkinsHistorySerializer
@api_view(["GET", "POST"])
def robot_list_api_view(request):
if request.method == "GET":
rb = Robot.objects.all()
serializer = RobotSerializer(rb, many=True)
filter_backends = [DjangoFilterBackend]
filterset_fields = ['robot']
return Response(serializer.data)
elif request.method == "POST":
return Response("You can do anything here")
@api_view(["GET", "POST"])
def robot_history_api_view(request):
if request.method == "GET":
rh = jenkinsHistory.objects.all()
serializer = jenkinsHistorySerializer(rh, many=True)
return Response(serializer.data)
elif request.method == "POST":
return Response("You can do anything here")
Как я могу использовать фильтр и базовый аутентификатор здесь, чтобы я мог получить отфильтрованное значение? Мне нужен URL/?robot=Demo этого типа, а также URL/?id отфильтрованных данных и хочу использовать базовый аутентификатор, как в этом коде
authentication_classes = [BasicAuthentication]
permission_classes = [IsAuthenticated]
Но это не работает в моем представлении. как получить отфильтрованные данные и базовый аут здесь?
Переменные, которые вы определили в представлении на основе функций, например filter_backends
, filterset_fields
и т.д., предназначены для использования в качестве атрибутов для drf-представлений на основе классов, только как документировано.
Измените представление на основе функций на представление на основе классов из:
@api_view(["GET", "POST"])
def robot_list_api_view(request):
if request.method == "GET":
rb = Robot.objects.all()
serializer = RobotSerializer(rb, many=True)
filter_backends = [DjangoFilterBackend]
filterset_fields = ['robot']
return Response(serializer.data)
elif request.method == "POST":
return Response("You can do anything here")
To:
from rest_framework import generics
class RobotListApiView(generics.ListAPIView)
queryset = Robot.objects.all()
serializer_class = RobotSerializer
filter_backends = [DjangoFilterBackend]
filterset_fields = ['robot']
В docs есть хороший пример на эту тему:
class ProductList(generics.ListAPIView): queryset = Product.objects.all() serializer_class = ProductSerializer filter_backends = [DjangoFilterBackend] filterset_fields = ['category', 'in_stock']
Это должно быть представление на основе классов, потому что, как документировано:
Одно из ключевых преимуществ представлений на основе классов заключается в том, что они позволяют вам компоновать кусочки многократно используемого поведения. Фреймворк REST использует преимущества этим, предоставляя ряд предварительно созданных представлений, которые обеспечивают часто используемые шаблоны.
Общие представления, предоставляемые REST framework, позволяют быстро создавать представления API, которые тесно связаны с вашими моделями базы данных.
Если вам действительно нужно использовать представления на основе функций, то вам придется все делать вручную (например, вручную писать код для фильтрации результатов), потому что, как было сказано выше, предварительно созданные представления, которые соответствуют операциям базы данных, таким как перечисление/фильтрация записей, реализуются через представления на основе классов. Вы ограничены этим API-декораторами при использовании представлений на основе функций.
Используя пользовательский фильтр, я добиваюсь фильтрации в представлении на основе функций вот код моего представления
from rest_framework.decorators import api_view, authentication_classes, permission_classes
from django_filters import rest_framework as filters
from rest_framework.permissions import IsAuthenticated
from rest_framework.authentication import BasicAuthentication
class RobotFilter(filters.FilterSet):
class Meta:
model = Robot
fields = ['robot']
@api_view(["GET", "POST"])
@authentication_classes([BasicAuthentication])
@permission_classes([IsAuthenticated])
def robot_list_api_view(request):
if request.method == "GET":
rb = Robot.objects.all()
filterset = RobotFilter(request.GET, queryset=rb)
if filterset.is_valid():
queryset = filterset.qs
serializer = RobotSerializer(queryset, many=True)
return Response(serializer.data)
elif request.method == "POST":
return Response("You can do anything here")