ROLE_CHOICES = (
("HEAD", "정교사"),
("ASSISTANT", "부교사"),
)
role = models.CharField(max_length=10, choices=ROLE_CHOICES, default="ASSISTANT")
head_teacher = models.ForeignKey(
"self",
null=True,
blank=True,
on_delete=models.SET_NULL,
related_name="assistance_teacher",
limit_choices_to={"role": "HEAD"},
# 제한 조건: {"role": "HEAD"}
# role 필드의 값이 "HEAD"(정교사)인 객체만 선택하여 head_teacher 필드에 저장할 수 있다.
# 즉, role 필드가 "ASSISTANT"(부교사)인 객체는 선택할 수 없습니다.
# 부교사를 정교사로 설정하는 실수를 방지하기 위해 사용.
)
related_name="assistance_teacher"
"role": "HEAD" 인 객체가 자신을 참조하는 부교사 객체를 역참조로 조회한다.assistants = head_teacher.assistant_teachers.all() def get_queryset(self):
# user = "token@toen.com"
user = self.request.user
if user == "HEAD":
queryset = Attendance.objects.filter(name__teacher__email=user)
year = self.request.query_params.get("year", None)
if year is not None:
queryset = queryset.filter(date__year=year)
return queryset
else:
queryset = Attendance.objects.filter(name__teacher__email=user.head_teacher)
year = self.request.query_params.get("year", None)
if year is not None:
queryset = queryset.filter(date__year=year)
return queryset
# AttendanceViewSet의 get_queryset
def get_queryset(self):
user = self.request.user
teacher_email = user.email if user.role == "HEAD" else user.head_teacher.email
queryset = Attendance.objects.filter(name__teacher__email=teacher_email)
return queryset
user.emailuser.head_teacher.emailqueryset은 role에 따라 분류된 email을 기준으로 Attendance 모델에서 필터링한 출석데이터 값을 갖는다.# utils.py 내 filter_by_year 메서드
def filter_by_year(self, queryset):
year = self.request.query_params.get("year", None)
if year is not None:
return queryset.filter(date__year=year)
return queryset
ueryset.filter(date__year=year) year 값이 존재하면 해당 연도의 데이터만 필터링하여 반환한다.# AttendanceViewSet의 create 메서드
serializer = BulkAttendanceSerializer(
data=request.data,
context={"queryset": self.get_queryset()},
def create(self, validated_data):
date = validated_data.get("date")
attendance_list = validated_data.get("attendance")
# context를 통해 요청한 사용자 정보 가져오기
user = self.context["request"].user
if user.role == "HEAD":
if Attendance.objects.filter(name__teacher=user, date=date).exists():
raise serializers.ValidationError(
{"detail": f"이미 {date}의 출석 데이터가 저장되어있습니다."},
)
else:
if Attendance.objects.filter(
name__teacher=user.head_teacher, date=date
).exists():
raise serializers.ValidationError(
{"detail": f"이미 {date}의 출석 데이터가 저장되어있습니다."},
)
self.context["request"].user를 통해 user의 role 필드를 검색하여 기존 데이터 존재 여부를 검증함 def create(self, validated_data):
date = validated_data.get("date")
attendance_list = validated_data.get("attendance")
# context를 통해 요청한 사용자 정보 가져오기
queryset = self.context["queryset"]
if queryset.filter(date=date).exists():
raise serializers.ValidationError(
{"detail": f"이미 {date}의 출석 데이터가 저장되어있습니다."},
)
self.context["queryset"]로 이미 정교사/부교사가 분류 된 user를 기준으로 필터링 된 Attendance의 데이터를 전달받아 serializser 내에서 user의 role을 통한 검증이 불필요하고 filter() 호출을 최소화.Django ORM은 ForeignKey 필드(name__teacher)에서 객체를 입력하면 자동으로 id 값으로 변환하여 쿼리를 실행한다.
두 코드 다 email을 기준으로 필터링 한다.
queryset = Attendance.objects.filter(name__teacher__email=user_email)
if Attendance.objects.filter(name__teacher=user, date=date).exists():