끄적이는 개발노트

260624_강의 정리 (Django 정리 - Form, View, Model) 본문

Python

260624_강의 정리 (Django 정리 - Form, View, Model)

크런키스틱 2026. 6. 24. 09:42
728x90

 

Web Framework · Django (2)
Django 정리 (2) — Form, View, Model의 3위 일체
  • Model · View · Form은 DB 연동 여부와 부모-자식 관계 표현 여부로 얽힌 3위 일체 구조
  • General View 6종으로 반복되는 CRUD를, ModelForm으로 Form-Model 연동을, FormSet으로 다중 입력을 처리
  • 폼 검증 흐름(is_bound → clean → is_valid)과 URL 역참조까지 한 번에 정리
🔺
1. Form-View-Model, 왜 3위 일체인가

"왜 Form은 Model이나 View 없이는 제대로 동작하지 않는가" — Django의 핵심 삼각 구조

  • Django에서 Model · View · Form은 서로 강하게 연결된 삼각 구조
  • Model 없이는 Form이 어떤 데이터를 받을지 모름
  • View 없이는 Form이 화면에 그려지거나 제출을 처리할 방법이 없음
  • 연결을 가르는 두 가지 기준 → DB 모델과의 연동 여부, 부모-자식(ForeignKey) 관계 표현 여부
💡 새 개념
3위 일체 Model–View–Form
  • Django 실무에서 가장 자주 함께 다뤄지는 세 요소
회원가입 기능 하나를 만들 때도 Model(User 정보 구조), Form(입력 검증), View(요청 처리)가 동시에 필요함
🔁
2. 전체 데이터 흐름

"DB에 저장된 데이터가 어떻게 화면까지 전달되는가" — Model에서 Template까지

Models (Class)
Objects (Manager)
QuerySet (쿼리 가능)
View (Contexts)
Template (Form class)
💡 새 개념
Manager Manager
  • 모델 클래스에 기본 제공되는 객체, .objects로 접근
Student.objects 가 바로 Manager 인스턴스
QuerySet QuerySet
  • Manager를 통해 만들어지는 "쿼리 가능한" 데이터 묶음, 아직 실행되지 않은 지연 평가(lazy) 객체
Student.objects.filter(kor__gte=80) 의 반환값이 QuerySet
핵심 요약
· request가 View에 들어오면 View는 Model에서 QuerySet을 받아 Context(딕셔너리)로 가공해 Template에 전달
· Admin도 같은 Model을 바탕으로 동작 — register()로 모델을 등록하면 관리자 화면이 자동 생성됨
⚙️
3. General View (Class-Based Generic View)

"반복되는 CRUD 로직을 매번 직접 작성해야 할까" — Django가 미리 만들어둔 6종 뷰

View대응 동작주로 쓰는 곳
ListView목록 조회 (GET)게시글 리스트
DetailView단일 항목 조회 (GET)게시글 상세
CreateView생성 (GET: 빈 폼 / POST: 저장)글쓰기
UpdateView수정 (GET: 기존값 채운 폼 / POST: 저장)글 수정
DeleteView삭제 (GET: 확인 화면 / POST: 삭제)글 삭제
FormViewModel과 무관한 폼 처리문의하기, 검색 폼
주의
· ListView, DetailView, CreateView, UpdateView, DeleteView는 기본적으로 Model과 연동되어 있음 (model = MyModel 속성만 지정하면 동작)
· FormView는 Model 연동이 필수가 아님 — DB 저장 없이 단순 입력 처리에 적합
📝
4. Form vs ModelForm

"입력값만 검증할 건지, DB 모델과 바로 연결할 건지"

구분forms.Formforms.ModelForm
DB 모델 연동직접 연동 없음, 필드 직접 정의Meta.model로 모델과 직접 연결
저장 방법View에서 직접 처리 필요form.save()로 즉시 DB 저장 가능
적합한 상황검색·로그인·문의 폼처럼 DB 저장이 불필요한 입력게시글 작성처럼 모델 데이터를 그대로 입력받는 경우
Form vs ModelForm
# Forms.Form
class ContactForm(forms.Form):
    email = forms.EmailField()
    message = forms.CharField(widget=forms.Textarea)

# Forms.ModelForm
class PostForm(forms.ModelForm):
    class Meta:
        model = Post
        fields = ['title', 'content']
5. 폼의 상태 확인과 검증

"제출된 폼이 유효한지 어떻게 판단하는가"

request
GET : 빈 폼
/
POST : 속이 찬 폼 (bound form)
💡 새 개념
Form.is_bound is_bound
  • 폼에 데이터가 채워졌는지 여부 (데이터 존재 여부와 유효성은 별개)
GET 요청으로 받은 빈 폼은 is_bound = False, POST로 제출된 폼은 is_bound = True
Form.clean() clean
  • 폼 전체 레벨의 검증 로직, 여러 필드를 함께 검사할 때 사용
비밀번호와 비밀번호 확인 필드가 일치하는지 검사하는 로직이 여기 들어감
Form.is_valid() is_valid
  • clean()을 포함한 모든 검증을 실행하고 통과 여부를 True/False로 반환
보통 View에서 if form.is_valid(): 형태로 사용
clean_필드명 clean_<field>
  • 특정 필드 하나만 따로 검증하고 싶을 때 사용하는 네이밍 규칙
clean_email(self) 메서드를 정의하면 email 필드만 따로 검증 가능
GET vs POST
· GET 요청 → 빈 폼(또는 기존 값이 채워진 초기 폼) 반환
· POST 요청 → 제출된 데이터가 담긴 폼(bound form)을 검증한 뒤 저장 또는 에러 반환
🧩
6. FormSet — 여러 개의 폼을 한 번에

"폼 하나가 아니라 여러 개를 동시에 다뤄야 할 때는"

종류설명사용 예시
FormSet동일한 Form을 여러 개 묶어서 처리여러 개의 연락처 입력
ModelFormSetModelForm을 여러 개 묶어서 처리, DB와 직접 연동여러 상품을 한 번에 등록
InlineFormSetForeignKey로 연결된 부모-자식 모델을 한 화면에서 함께 처리주문(부모) 안에 여러 주문 항목(자식) 입력
선택 기준
· 핵심 차이는 DB 모델과의 연동 여부(FormSet vs ModelFormSet)와 부모-자식 관계 표현 여부(InlineFormSet)
· InlineFormSet은 inlineformset_factory()로 생성하며, 게시글-댓글처럼 1:N 관계를 한 화면에서 다룰 때 유용
🖼️
7. Form을 HTML로 렌더링하기

"Form 객체를 화면에 어떻게 보여줄 것인가"

태그렌더링 형태
{{ form.as_table }}<tr> 행으로 구성, <table> 태그로 감싸야 함
{{ form.as_p }}각 필드를 <p> 태그로 감쌈
{{ form.as_ul }}각 필드를 <li> 태그로 감쌈, <ul>로 감싸야 함
{{ form.as_div }}Django 4.1+ 추가, <div> 기반 — 커스텀 스타일링에 가장 유연
참고
· 위 4종보다 실무에서는 필드를 하나씩 직접 꺼내 커스텀 마크업을 짜는 경우가 더 많음
· 예: {{ form.email.label }}, {{ form.email }}
🔗
8. URL 매개변수와 이름 기반 역참조

"URL에 변수를 어떻게 담고, 코드에서는 그 URL을 어떻게 다시 찾아가는가"

URL 매개변수 처리 — class / function
# urls.py — path converter로 변수 전달
urlpatterns = [
    path('post/<int:pk>/', PostDetailView.as_view(), name='post_detail'),
]

# FBV에서 받기
def post_detail(request, pk):
    post = get_object_or_404(Post, pk=pk)
    ...

# CBV에서 받기 — self.kwargs로 접근
class PostDetailView(DetailView):
    model = Post
    def get_object(self):
        return get_object_or_404(Post, pk=self.kwargs['pk'])
💡 새 개념
name → URL 역참조 reverse lookup
  • urls.py에서 지정한 name 값으로, 실제 경로를 몰라도 URL을 찾아갈 수 있는 방법
Template에서는 {% url 'post_detail' pk=post.pk %}, View/코드에서는 reverse('post_detail', kwargs={'pk': post.pk})
요약
· URL을 하드코딩하지 않고 name으로 참조하면, 나중에 경로(path())가 바뀌어도 코드 수정이 필요 없음
전체 요약
· Model–View–Form은 서로 떼어 생각할 수 없는 3위 일체 구조
· General View는 반복되는 CRUD를, ModelForm은 모델 연동을, FormSet은 다중 입력을 각각 줄여주는 역할
· URL의 name 기반 역참조는 유지보수성을 위한 Django의 핵심 관례
728x90