Django - Learned

김기훈·2025년 11월 20일

Django

목록 보기
6/17

새롭게 알게 된 코드

2025/11/21

DRF

many=True

  • 기본값: False
  • 여러 개의 객체(리스트)를 직렬화할 때 사용
    • QuerySet 같이 여러 개의 객체를 Serializer로 처리할 때 사용
    • ex. Post.objects.all(), User.objects.filter(...)
posts = Post.objects.all()
serializer = PostSerializer(posts, many=True)

# 여러 개의 Post 객체를 JSON 리스트로 변환
# [{}, {}, ...] 형태가 됨

만약 many=True 없이 QuerySet을 넘기면?

  • TypeError: 'Post' object is not iterable
    • multiple objects인데 single object로 받으려고 해서 에러

raise_exception=True

  • 기본값: False
  • 검증 실패 시 예외를 자동으로 발생
    • Serializer 검증(.is_valid()) 할 때 사용
    • 잘못된 요청이 들어오면 DRF가 자동으로 400 Bad Request 응답을 보내게 하고 싶을 때
  • 직접 if문으로 검사할 필요가 없어져서 개발자의 코드가 깔끔해짐.
serializer = UserSerializer(data=request.data)
serializer.is_valid(raise_exception=True)

# 유효성 검증 실패 시 DRF가 자동으로 예외를 발생시키고
## Response는  "email": ["이미 존재하는 이메일입니다"]

partial=True

  • 기본값: False
  • PATCH(부분 업데이트)에서 사용하는 옵션
    • partial=False → 모든 필드가 유효하게 들어와야 함.
    • partial=True → 일부 필드만 들어와도 OK.
# PATCH 요청 
{
  "nickname": "새닉네임"
}

# Serializer 사용
serializer = UserSerializer(user, data=request.data, partial=True)

## nickname만 업데이트하고 password, email 등 나머지 필드는 검사하지 않음(없어도 OK)

만약 partial=True 없이 PATCH 요청을 하면?

  • "password field is required" 같은 에러 발생
    • 즉, 필수 필드가 입력되어야만 통과

2025/11/23

get_user_model()

  • 현재 프로젝트에서 사용 중인 “User 모델”을 가져오는 Django 함수
    • Django가 커스텀 User 모델을 사용하더라도, 항상 올바른 User 모델을 가져오게 해주는 안전한 함수
from django.contrib.auth.models import User
# 커스텀 User를 쓰는 프로젝트에서는 잘못된 User 모델을 가져오게 됨
## 에러 발생 & 데이터 충돌

from django.contrib.auth import get_user_model
User = get_user_model()
# 기본 User 모델을 쓰든 / 커스텀 User 모델을 쓰든 / settings.AUT_USER_MODEL을 가리키든
## 항상 현재 프로젝트에서 실제로 사용 중인 User 모델을 반환

User 모델을 만든 적이 없는데 왜 ForeignKey로 연결이 가능한가?

  • Django에는 기본 User 모델이 내장

    • django.contrib.auth 앱 안에 Django가 자체 제공하는 User 모델이 있음.
  • Django 프로젝트 생성하면 기본적으로 아래 앱이 INSTALLED_APPS에 들어있음

    • 'django.contrib.auth'
      • 안에는 User, Group, Permission 등 이미 정의된 모델들이 포함
      • migration도 Django가 자동으로 만들어 둔 상태
      • 그걸 migrate 하면 DB에 User 테이블이 생성됨.
  • ForeignKey가 가능한 이유

from django.contrib.auth import get_user_model
User = get_user_model()

class Blog(models.Model):
    author = models.ForeignKey(User, on_delete=models.CASCADE)

# 직접 User 모델을 정의하지 않아도 Django의 기본 User 모델이 자동 사용됨
## DB에는 이미 auth_user라는 User 테이블이 생성됨
### 결과 → 외래키 연결 OK.
  • 커스텀 User 모델을 만들면?

    • settings.py 에서
      • AUTH_USER_MODEL = "accounts.CustomUser" 이렇게 설정
        • get_user_model()은 커스텀 User를 반환하고, 외래키도 자동으로 그 모델로 연결됨.

read_only_fields

  • 수정 불가 필드

2025/11/25

유용한 날짜 함수

from datetime import datetime, timedelta
import calendar

def get_daily_range():
    today = datetime.now().date()
    start = datetime.combine(today, datetime.min.time())
    end = datetime.combine(today, datetime.max.time())
    return start, end

def get_last_day_range():
    yesterday = datetime.now().date() - timedelta(days=1)
    start = datetime.combine(yesterday, datetime.min.time())
    end = datetime.combine(yesterday, datetime.max.time())
    return start, end

def get_week_range():
    today = datetime.now().date()
    start = today - timedelta(days=today.weekday())
    end = start + timedelta(days=6)
    return datetime.combine(start, datetime.min.time()), datetime.combine(end, datetime.max.time())

def get_last_week_range():
    today = datetime.now().date()
    end = today - timedelta(days=today.weekday() + 1)
    start = end - timedelta(days=6)
    return datetime.combine(start, datetime.min.time()), datetime.combine(end, datetime.max.time())

def get_month_range():
    today = datetime.now().date()
    start = today.replace(day=1)
    last_day = calendar.monthrange(today.year, today.month)[1]
    end = today.replace(day=last_day)
    return datetime.combine(start, datetime.min.time()), datetime.combine(end, datetime.max.time())

def get_last_month_range():
    today = datetime.now().date()
    first_day_this_month = today.replace(day=1)
    last_month_end = first_day_this_month - timedelta(days=1)
    start = last_month_end.replace(day=1)
    end = last_month_end
    return datetime.combine(start, datetime.min.time()), datetime.combine(end, datetime.max.time())

def str(self)

  • admin 등에서 읽을 때 보여지는 문자열

dategte / datelte

  • 그냥 변수 이름이 아닌 실제 Django ORM 기능(lookup)
  • transacted_at__date

    • transacted_at → DateTimeField
    • __date → datetime에서 날짜(date)만 추출
    • __gte, __lte → 비교 연산 조건
      • transacted_at__date__gte=self.start_date
      • "transacted_at 의 날짜 부분이 start_date 이상인 데이터"
  • 즉, 실제로 DB에서 날짜만 비교하도록 만들어주는 기능
형태역할
field__gtefield ≥ value
field__ltefield ≤ value
field__containsLIKE %value%
field__datedatetime → 날짜 변환
field__yeardatetime.year
field__monthdatetime.month
field__daydatetime.day
field__date__range날짜 범위

새롭게 알게 된 이론

2025/11/27


구분언제 쓰는가어디에서 값이 오는가예시
request.query_paramsGET 요청URL 쿼리스트링/analysis/list/?period=DAILY
request.dataPOST/PUT/PATCH 요청JSON body, form-dataPOST로 분석 생성 요청

query_params

  • query_params = URL 뒤에 붙은 ?key=value 값을 가져오는 DRF 객체

  • Django REST Framework(DRF) 에서 GET 요청의 쿼리스트링(parameters)을 가져올 때 사용하는 객체
    • Django에는 원래 request.GET 하지만 DRF는 API 스타일로 통일하기 위해 request.query_params
  • ex.

    • 요청: GET /analysis/api/list/?period=DAILY&type=graph
    • period=DAILY / type=graph -> query params(쿼리 파라미터)
    • period = self.request.query_params.get("period") -> 결과: "DAILY"

data

  • request.data는 POST 요청 body에서 값을 꺼내는 역할
POST /analysis/api/create/
Content-Type: application/json

{
  "type": "CATEGORY",
  "about": "MONTHLY",
  "description": "이번달 분석입니다"
}
  • analysis_type = request.data.get("type") -> CATEGORY

Django(DRF)에서의 용어 비교

가져오는 값예시접근 방식
URL Path Params/analysis/123/ → 123kwargs["id"]
Query Params?period=DAILYrequest.query_params["period"]
Body Params (POST)form/json 데이터request.data["field"]
profile
안녕하세요.

0개의 댓글