class Todo(TrackingModel) :
title = models.CharField(max_length=255)
desc = models.TextField()
is_complete = models.BooleanField(default=False)
owner = models.ForeignKey(to=User,on_delete=models.CASCADE)
def __str__(self) :
return self.title
class TodoSerializer(ModelSerializer) :
class Meta:
model=Todo
fields = ('title','desc','is_complete',)
class CreateTodoAPIView(CreateAPIView) :
serializer_class =TodoSerializer
permission_classes=(IsAuthenticated,)
def perform_create(self, serializer):
return serializer.save(owner=self.request.user)
# CreateAPIView
class CreateAPIView(mixins.CreateModelMixin,
GenericAPIView):
"""
Concrete view for creating a model instance.
"""
def post(self, request, *args, **kwargs):
return self.create(request, *args, **kwargs)
#mixins.CreateModelMixin
class CreateModelMixin:
def create(self, request, *args, **kwargs):
serializer = self.get_serializer(data=request.data)
serializer.is_valid(raise_exception=True)
self.perform_create(serializer)
headers = self.get_success_headers(serializer.data)
return Response(serializer.data, status=status.HTTP_201_CREATED, headers=headers)
def perform_create(self, serializer):
serializer.save()
def get_success_headers(self, data):
try:
return {'Location': str(data[api_settings.URL_FIELD_NAME])}
except (TypeError, KeyError):
return {}
class TodoListAPIView(ListAPIView) :
serializer_class = TodoSerializer
permission_classes=(IsAuthenticated,)
queryset=Todo.objects.all()
def get_queryset(self):
return Todo.objects.filter(owner=self.request.user)
List API View는 get 요청에 대해 queryset 형태로 데이터를 리턴하는 클래스이다.
해당 클래스에는 필수적으로 queryset을 정의해야 하며, 이를 정의하면 다른 override 없이 queryset을 리턴한다.
class TodoListAPIView(ListAPIView) :
serializer_class = TodoSerializer
queryset=Todo.objects.all()
하지만 queryset에 대해서 custom하여 request에 담긴 data를 가지고 오고 싶은 경우 get_queryset 함수를 재정의 하여 해결할 수 있다.
class TodoListAPIView(ListAPIView) :
serializer_class = TodoSerializer
def get_queryset(self):
return Todo.objects.filter(owner=self.request.user)
해당 TodoListAPIView의 경우 get_queryset을 재정의 했기 때문에, queryset을 요청하지 않아도 되며, queryset 요청에 대해 요청한 유저가 작성한 유저인 경우에만 불러온다.
일반적으로 queryset을 사용하여 보다 깔끔히 표시하지만, request에서 data를 가져와야 할 경우에는 필수적으로 get_queryset을 사용해야한다.
https://stackoverflow.com/questions/19707237/use-get-queryset-method-or-set-queryset-variable
queryset
서버를 시작할 때 쿼리 세트가 한 번만 생성되며, 반면 get_queryset
에 모든 요청에 대해 메서드가 호출된다.
유용한 또 다른 예 get_queryset
는 콜러블을 기반으로 필터링하려는 경우입니다. 예를 들어 오늘의 투표를 반환합니다.
class IndexView(generic.ListView):
def get_queryset(self):
"""Returns Polls that were created today"""
return Poll.active.filter(pub_date=date.today())
queryset를 설정하여 동일한 작업을 시도 하면 뷰가 로드될 때 queryset
의 date.today()
가 한 번만 호출되고 잠시 후 뷰가 잘못된 결과를 표시합니다.
class IndexView(generic.ListView):
# don't do this!
queryset = Poll.active.filter(pub_date=date.today())
class TodosAPIView(ListCreateAPIView) :
serializer_class =TodoSerializer
permission_classes=(IsAuthenticated,)
def perform_create(self, serializer):
return serializer.save(owner=self.request.user)
# queryset=Todo.objects.all()
def get_queryset(self):
return Todo.objects.filter(owner=self.request.user)
class TodoDetailAPIView(RetrieveUpdateDestroyAPIView) :
serializer_class =TodoSerializer
permission_classes=(IsAuthenticated,)
lookup_field="id"
def get_queryset(self):
return Todo.objects.filter(owner=self.request.user)
class RetrieveUpdateDestroyAPIView(mixins.RetrieveModelMixin,
mixins.UpdateModelMixin,
mixins.DestroyModelMixin,
GenericAPIView):
"""
Concrete view for retrieving, updating or deleting a model instance.
"""
def get(self, request, *args, **kwargs):
return self.retrieve(request, *args, **kwargs)
def put(self, request, *args, **kwargs):
return self.update(request, *args, **kwargs)
def patch(self, request, *args, **kwargs):
return self.partial_update(request, *args, **kwargs)
def delete(self, request, *args, **kwargs):
return self.destroy(request, *args, **kwargs)