-
Notifications
You must be signed in to change notification settings - Fork 5
Utils
Utils 앱은 Safe Eye 프로젝트에서 공통적으로 사용되는 기능들을 제공하는 앱입니다.
이 앱은 다른 앱에서 사용할 수 있는 태그(Tag)와 상태(Status) 기능을 제공하고, 이를 다른 모델에 추가할 수 있도록 TagMixin과 StatusMixin이 있고, 사용자 정의 404 오류 처리와 권한 제어를 위한 Mixin과 권한 클래스가 있습니다.
Tag 모델과 Status 모델은 GenericForeignKey를 사용하여 다양한 모델에 Tag 와 Status 를 추가할 수 있습니다.
예시 코드
from django.contrib.contenttypes.models import ContentType
from .models import Status
# 상태 생성
status = Status.objects.create(
available=True,
content_type=ContentType.objects.get_for_model(Alarm),
object_id=alarm.id
)Status 모델 사용법을 간단한 예시로 넣어봤습니다. Tag 모델도 사용법은 비슷합니다. Status 모델은 여러 다른 모델에 상태를 추가할 수 있게 하려고 만들었습니다. available 필드가 있어서 사용 가능 여부를 나타낼 수 있습니다.
TagMixin과 StatusMixin은 모델에 태그와 상태 기능을 추가하기 위한 추상 모델입니다. 모델에서 이 Mixin을 상속받으면 Tag 와 Status 를 연결할 수 있습니다. Tag 와 Status 모델을 그대로 사용할 수도 있지만 이렇게 Mixin을 만든 것은 좀 더 다양한 모델에 사용될 수도 있어서 만들었습니다. Tag와 Status를 여러 모델에서 사용해야 하고, 모델 간의 관계를 낮추고, 부담을 줄인다는 면에서는 Mixin 을 사용하는 것이 좋을 수 있습니다.
(대규모 프로젝트에서 모델 간의 관계가 많이 추가된다면 쿼리 성능 저하가 발생할 수 있습니다.)
프로젝트가 크지 않고 Tag 와 Status 사용하는 모델이 적다면 Mixin 없이 Tag 와 Status 모델을 사용하는 것이 더 좋을 수 있습니다.
예시 코드
from django.db import models
from .models import TagMixin, StatusMixin
class Alarm(TagMixin, StatusMixin, models.Model):
# Alarm 모델 필드 정의
...
)위의 코드처럼 모델에서 TagMixin과 StatusMixin을 상속받아 사용하면, Alarm 모델에 태그와 상태 기능을 쉽게 추가할 수 있고, 알람 데이터에 태그와 상태를 분류하고 관리할 수 있습니다.
TagViewSet과 StatusViewSet은 각각 Tag 모델과 Status 모델에 대한 CRUD 작업을 수행합니다.
# alarm/views.py
from rest_framework import viewsets
from .models import Tag, Status
from .serializers import TagSerializer, StatusSerializer
from .mixins import IsAuthorOrReadOnly
from .views import CustomPageNumberPagination
class TagViewSet(viewsets.ModelViewSet):
queryset = Tag.objects.all()
serializer_class = TagSerializer
permission_classes = [IsAuthorOrReadOnly]
pagination_class = CustomPageNumberPagination
filterset_fields = ['tag_type', 'tag_content']
class StatusViewSet(viewsets.ModelViewSet):
queryset = Status.objects.all()
serializer_class = StatusSerializer
permission_classes = [IsAuthorOrReadOnly]
pagination_class = CustomPageNumberPagination
filterset_fields = ['available']TagViewSet과 StatusViewSet은 Django REST Framework의 ModelViewSet을 상속받아 구현되고, Tag 모델과 Status 모델에 대한 CRUD 작업을 처리할 수 있습니다. urls.py 에서 ViewSet을 라우터에 등록하면 API 엔드포인트가 생성됩니다. API 엔드포인트를 통해 Tag와 Status 모델에 대한 CRUD 작업을 수행할 수 있고, HTTP 요청을 보낼 수 있습니다. 이를 통해 필요한 데이터를 효과적으로 조회하고 관리할 수 있습니다.
GET /tags/ Tag 객체의 목록을 조회합니다.
POST /tags/ 새로운 Tag 객체를 생성합니다.
GET /tags/{id}/ 특정 Tag 객체의 상세 정보를 조회합니다.
PUT /tags/{id}/ 특정 Tag 객체를 수정합니다.
PATCH /tags/{id}/ 특정 Tag 객체를 부분적으로 수정합니다.
DELETE /tags/{id}/ 특정 Tag 객체를 삭제합니다.
GET /tags/?tag_type={tag_type} 특정 tag_type에 해당하는 Tag 객체만 조회합니다.
GET /tags/?tag_content={tag_content} 특정 tag_content에 해당하는 Tag 객체만 조회합니다.
GET /tags/?page={page_number}&page_size={page_size} 지정된 페이지 번호와 페이지 크기로 Tag 객체를 조회합니다.
필터링
GET /tags/?tag_type=category tag_type이 'category'인 Tag 객체만 조회합니다.
GET /statuses/?available=true available이 true인 Status 객체만 조회합니다.
GET /tags/?page=1&page_size=10 Tag 객체의 첫 번째 페이지를 조회하고, 페이지당 10개의 객체를 반환합니다.
GET /status/ Status 객체의 목록을 조회합니다. 페이지네이션과 필터링을 지원합니다.
POST /status/ 새로운 Status 객체를 생성합니다.
GET /status/{id}/ 특정 Status 객체의 상세 정보를 조회합니다.
PUT /status/{id}/ 특정 Status 객체를 수정합니다.
PATCH /status/{id}/ 특정 Status 객체를 부분적으로 수정합니다.
DELETE /status/{id}/ 특정 Status 객체를 삭제합니다.
GET /status/?available={available} 특정 available 값에 해당하는 Status 객체만 조회합니다.
GET /status/?content_type={content_type_id} 특정 content_type의 ID에 해당하는 Status 객체만 조회합니다.
GET /status/?object_id={object_id} 특정 object_id에 해당하는 Status 객체만 조회합니다.
GET /status/?page={page_number}&page_size={page_size} 지정된 페이지 번호와 페이지 크기로 Status 객체를 조회합니다.
필터링
GET /status/?available=true available이 true인 Status 객체만 조회합니다.
GET /status/?content_type=3 content_type의 ID가 3인 Status 객체만 조회합니다.
GET /status/?object_id=42 object_id가 42인 Status 객체만 조회합니다.
Custom404Mixin을 사용하여 404 에러 처리를 커스터마이징할 수 있습니다.
예시 코드
# notice/views.py
from utils.mixins import Custom404Mixin
class NoticeViewSet(Custom404Mixin, viewsets.ModelViewSet):
queryset = Notice.objects.order_by("-created_at")
serializer_class = NoticeSerializer
pagination_class = CustomPageNumberPagination
filter_fields = ["id", "title"]
custom_404_message = "해당 공지사항을 찾을 수 없습니다."NoticeViewSet에서 Custom404Mixin을 사용하여 404 에러 처리를 커스터마이징할 수 있습니다.
custom_404_message 속성을 통해 사용자 정의 에러 메시지를 설정할 수 있습니다.
예시 코드
# alarm/serializers.py
class AlarmSerializer(serializers.ModelSerializer):
tags = TagSerializer(many=True, required=False)
status = StatusSerializer(many=True, required=False)
log_format = serializers.ReadOnlyField(source="to_log_format")
class Meta:
model = Alarm
fields = [
"id",
"admin",
"camera_id",
"alarm_type",
"alarm_content",
"risk",
"custom_message",
"created_at",
"updated_at",
"tags",
"status",
"log_format",
]AlarmSerializer에서 TagSerializer와 StatusSerializer를 사용하여 태그와 상태 정보를 직렬화할 수 있고, 알람 데이터와 함께 관련된 태그와 상태 정보를 API 응답에 포함시킬 수도 있습니다.
IsAuthorOrReadOnly 클래스는 Django REST framework의 사용자 정의 권한 클래스입니다.
예시코드
class AlarmViewSet(Custom404Mixin, viewsets.ModelViewSet):
queryset = Alarm.objects.order_by("-created_at")
serializer_class = AlarmSerializer
permission_classes = [IsAuthorOrReadOnly]
pagination_class = CustomPageNumberPagination
filter_backends = [DjangoFilterBackend, filters.SearchFilter]
filterset_fields = ["camera_id", "alarm_type__code", "risk__level"]
search_fields = ["alarm_content", "custom_message"]
custom_404_message = "해당 알람을 찾을 수 없습니다."permission_classes = [IsAuthorOrReadOnly] 처럼 사용하면 됩니다.
- 요청의
HTTP메서드가 안전한 메서드(GET,HEAD,OPTIONS)인 경우, 모든 사용자에게 권한을 허용합니다. - 요청의
HTTP메서드가 안전하지 않은 메서드(POST,PUT,PATCH,DELETE)인 경우에는 인증된 사용자만 권한을 허용합니다. - 인증된 사용자의 역할이
admin또는superuser인 경우, 해당 객체의 소유자(작성자)와 일치하는 경우에만 권한을 허용합니다. - 인증된 사용자의 역할이
admin또는superuser가 아닌 경우, 권한을 거부합니다.
CustomPageNumberPagination은 페이지 크기를 조정할 수 있는 사용자 정의 페이지네이션 클래스입니다. 뷰에서 이 페이지네이션 클래스를 사용하면 클라이언트에서 페이지 크기를 지정할 수 있습니다.
예시코드
class AlarmViewSet(Custom404Mixin, viewsets.ModelViewSet):
queryset = Alarm.objects.order_by("-created_at")
serializer_class = AlarmSerializer
permission_classes = [IsAuthorOrReadOnly]
pagination_class = CustomPageNumberPagination
filter_backends = [DjangoFilterBackend, filters.SearchFilter]
filterset_fields = ["camera_id", "alarm_type__code", "risk__level"]
search_fields = ["alarm_content", "custom_message"]
custom_404_message = "해당 알람을 찾을 수 없습니다."pagination_class = CustomPageNumberPagination 이렇게 사용하면 됩니다. pagination_class 속성은 뷰셋에서 사용할 페이지네이션 클래스를 지정합니다. CustomPageNumberPagination은 페이지 크기를 조정할 수 있는 사용자 정의 페이지네이션 클래스입니다.
위의 예시 코드들을 참고해서 utils 앱의 모델과 클래스를 사용할 수 있습니다. 여러 모델에 태그와 상태 기능을 추가하고, 권한 제어와 페이지네이션, 필터링 등의 기능을 활용할 수 있습니다.