pk 대신 slug나 uuid로 객체를 조회하는 get_object 커스텀

DRF에서 기본 pk 대신 slug나 uuid를 사용하여 더 의미있고 안전한 API URL을 만드는 방법

왜 pk 대신 다른 식별자를 사용하나?

  • pk 사용 시 문제점: 데이터베이스 정보 노출, 추측 가능한 URL, SEO 불리

  • slug 장점: 사용자 친화적 URL, SEO 최적화 (예: /posts/my-first-post/)

  • uuid 장점: 보안성, 추측 불가능, 분산 시스템에 적합 (예: /orders/a1b2c3d4-e5f6-.../)

lookup_field로 간단하게 구현

모델에 필드 추가

class Post(models.Model):
    uuid = models.UUIDField(default=uuid.uuid4, unique=True)
    slug = models.SlugField(max_length=250, unique=True)
    title = models.CharField(max_length=200)
    
    def save(self, *args, **kwargs):
        if not self.slug:
            self.slug = slugify(self.title, allow_unicode=True)
        super().save(*args, **kwargs)

ViewSet에서 설정

class PostViewSet(viewsets.ModelViewSet):
    queryset = Post.objects.all()
    serializer_class = PostSerializer
    lookup_field = 'slug'  # 또는 'uuid'

get_object 직접 오버라이드

pk와 slug 동시 지원

class PostViewSet(viewsets.ModelViewSet):
    def get_object(self):
        queryset = self.get_queryset()
        identifier = self.kwargs['pk']
        
        if identifier.isdigit():
            filter_kwargs = {'pk': identifier}
        else:
            filter_kwargs = {'slug': identifier}
        
        obj = get_object_or_404(queryset, **filter_kwargs)
        self.check_object_permissions(self.request, obj)
        return obj

주의사항

  • 고유성 보장: unique=True로 URL에서 객체를 유일하게 식별

  • 권한 체크: check_object_permissions 호출 필수

Last updated