Django REST 필터링 자습서 - 현재 사용자로 필터링(2부)

앙트레



part I에서 repo 설정 방법, HTTP 요청 전송 및 Django REST 필터링에 대한 몇 가지 기본 개념을 살펴보았습니다.

이 두 번째 부분에서는 뷰/쿼리 세트/객체를 user 로, 더 정확하게는 현재 인증된 사용자로 제한합니다.

작성자 목록 끝점 — /authors/ 은 현재 사용자에 속하는지 여부에 관계없이 모든 항목을 표시합니다.

$ http :8000/authors

[
    {
        "first_name": "Name1",
        "full_name": "Name1 Surname1",
        "id": 1,
        "last_name": "Surname1",
        "user": 1
    },
    {
        "first_name": "Name2",
        "full_name": "Name2 Surname2",
        "id": 2,
        "last_name": "Surname2",
        "user": null
    },
    {
        "first_name": "Name3",
        "full_name": "Name3 Surname3",
        "id": 3,
        "last_name": "Surname3",
        "user": 3
    }
]


현재 인증된 사용자만 소유한 항목을 반환하기 위해 어떻게 동작을 변경할 수 있습니까?

NOTE

You can find the code we're working on this tutorial series in this repository: django-rest-filtering-tutorial

You don't need to download and setup the repository in order to follow this series, however I'd like to encorauge to do so, since while you play you learn better as always.



현재 사용자



이는 요청한 현재 인증된 사용자에게만 관련 결과가 반환되도록 쿼리 세트를 필터링하는 일반적인 필터 사용 중 하나입니다.

이를 위해 get_queryset에서 자세히 살펴본 것처럼 기본값default filtering을 재정의합니다.

현재 사용자로 작성자 목록 끝점을 필터링해 보겠습니다.

from rest_framework import generics

from src.authors.models import Author
from src.authors.serializers import AuthorSerializer


class AuthorListView(generics.ListAPIView):
    serializer_class = AuthorSerializer

    def get_queryset(self):
        """
        This view returns a list of all the authors for the currently
        authenticated user.

        Returns empyt list if user Anonymous
        """
        user = self.request.user

        if not user.is_anonymous:
            return Author.objects.filter(user=user)

        return Author.objects.none()


NOTE

In our repo we use ModelViewSet for authors endpoint. You can update it like above.



repo에서 관련 AuthorSerializerAuthor 모델을 볼 수 있지만 쉽게 액세스할 수 있도록 여기에 두었습니다. 그것들을 조사하려면 아래 섹션을 확장하십시오.

AuthorSerializer 및 Author 모델
AuthorSerializer에서 src/authors/serializers.py:

# src/authors/serializers.py
from rest_framework import serializers

from src.authors.models import Author


class AuthorSerializer(serializers.ModelSerializer):

    class Meta:
        model = Author
        fields = ("id", "user", "first_name", "last_name", "full_name")
        read_only_fields = ("full_name",)

Author src/authors/model.py의 모델:

# src/authors/model.py
from django.db import models
from django.conf import settings

USER = settings.AUTH_USER_MODEL


class Author(models.Model):
    """
    Author entity

    Provides first_name and last_name, since he/she can write unter a Pen Name
    """
    user = models.ForeignKey(to=USER, on_delete=models.DO_NOTHING, blank=True, null=True)
    first_name = models.CharField(max_length=255)
    last_name = models.CharField(max_length=255)

    def __str__(self):
        return f"{self.first_name} {self.last_name}"

    @property
    def full_name(self):
        return f"{self.first_name} {self.last_name}"





이제 populate_db.py에서 생성한 사용자 중 한 명의 사용자 이름과 암호를 포함하여 성공적인 요청을 할 수 있습니다.

$ http -a "User1:1234" ":8000/authors/"

[
    {
        "first_name": "Name1",
        "full_name": "Name1 Surname1",
        "id": 1,
        "last_name": "Surname1",
        "user": 1
    },
]


이제 알 수 있듯이 세 개가 아닌 하나의 객체만 반환합니다.

익명 또는 인증되지 않은 사용자로 요청하면 다음과 같은 정보를 받게 됩니다.

$ http ":8000/authors/"

[]


사용자 인증 및 권한



일반적으로 authenticationpermission 레이어/로직을 분리하는 것이 좋습니다. 이 목표를 위해 뷰별 또는 뷰셋별로 authentication_classespermission_classes를 사용할 수 있습니다.

from rest_framework import generics
from rest_framework.authentication import SessionAuthentication, BasicAuthentication
from rest_framework.permissions import IsAuthenticated

from src.authors.models import Author
from src.authors.serializers import AuthorSerializer


class AuthorListView(generics.ListAPIView):
    serializer_class = AuthorSerializer
    authentication_classes = (SessionAuthentication, BasicAuthentication)
    permission_classes = (IsAuthenticated,)

    def get_queryset(self):
        """
        This view returns a list of all the authors for the currently
        authenticated user.
        """
        user = self.request.user

        return Author.objects.filter(user=user)


또 다른 방법은 DEFAULT_AUTHENTICATION_CLASSES 설정을 사용하여 전역적으로 기본 인증을 설정하는 것입니다.

# settings.py
REST_FRAMEWORK = {
    "DEFAULT_AUTHENTICATION_CLASSES": [
        "rest_framework.authentication.BasicAuthentication",
        "rest_framework.authentication.SessionAuthentication",
    ]
}


INFO

In the repo these are disabled, you can set them globally if you comment out the related lines at the end of the setting.py file.



이제 뷰가 ​​다음과 같이 더 깔끔해 보일 것입니다.

# src/authors/views.py
from rest_framework import generics

from src.authors.models import Author
from src.authors.serializers import AuthorSerializer


class AuthorListView(generics.ListAPIView):
    serializer_class = AuthorSerializer

    def get_queryset(self):
        """
        This view returns a list of all the authors for the currently
        authenticated user.
        """
        return Author.objects.filter(user=self.request.user)

authenticationpermissions에 대한 자세한 내용은 다음을 참조하십시오.
  • drf authentication
  • drf permissions

  • 커스텀 필터백엔드



    자체 일반 필터링 백엔드를 제공할 수도 있다는 또 다른 방법이 있습니다.

    그렇게 하려면 BaseFilterBackend 클래스를 재정의하고 .filter_queryset 메서드를 재정의하십시오. 메서드는 필터링된 새 쿼리 집합을 반환해야 합니다.

    클라이언트가 검색 및 필터링을 수행하도록 허용할 뿐만 아니라 일반 필터 백엔드는 지정된 요청 또는 사용자에게 표시되어야 하는 개체를 제한하는 데 유용할 수 있습니다.

    현재 사용자 로직에 대해 IsOwnerFilterBackend를 작성해 보겠습니다.

    # src/authors/filters.py
    from django_filters import rest_framework as filters
    
    
    class IsOwnerFilterBackend(filters.BaseFilterBackend):
        """
        Filter that only allows users to get their own objects
        """
        def filter_queryset(self, request, queryset, view):
            return queryset.filter(owner=request.user)
    
    

    AuthorListView에 이 필터를 추가합니다.

    # src/authors/views.py
    from rest_framework import generics
    from django_filters import rest_framework as filters
    
    from src.authors.models import Author
    from src.authors.serializers import AuthorSerializer
    from src.authors.filters import IsOwnerFilterBackend
    
    
    class AuthorListView(generics.ListAPIView):
        serializer_class = AuthorSerializer
        queryset = Author.objects.all()
        filter_backends = (IsOwnerFilterBackend,)
        filterset_fields = ("user",)
    


    이제 요청을 보내면 관련 작성자만 사용자에게 받습니다.

    이 방법에 대한 한 가지 참고 사항; 위에서 이미 본 것처럼 보기에서 재정의get_queryset()하여 동일한 동작을 달성할 수 있지만 필터 백엔드를 사용하면 이 제한을 여러 보기에 더 쉽게 추가하거나 전체 API에 적용할 수 있습니다.

    이 필터 백엔드를 전역 기본 백엔드로 만들 수도 있습니다.

    # settings.py
    REST_FRAMEWORK = {
        "DEFAULT_FILTER_BACKENDS": ["src.authors.filters.IsOwnerFilterBackend"],
    }
    


    결론



    이 튜토리얼에서 우리는 요청을 한 현재 인증된 사용자와 관련된 결과만 반환되도록 쿼리 세트를 필터링하는 방법을 배웠습니다.

    이 자습서 시리즈의 다음 부분에서 뵙겠습니다.

    모두 끝났습니다!

    좋은 웹페이지 즐겨찾기