Django 기초 - 공부시간 기록기 만들기1번부터3번까지 코드정리

HY_1023·2026년 3월 18일

MENTOS

목록 보기
9/19

3. 1편 상태 먼저 점검하기

모델 데이터가 중요 --> URL --> VIEW --> TRMPLETE

VIEW는 많은역할을 함 그래서 1편에서 2편으로 넘어갈때 코드가 동일한지 확인체크


ModelForm을 만들고, 함수형 View 기준으로 공부기록 생성(Create), 상세(Detail), 수정(Update), 삭제(Delete), 페이지네이션까지 완성하며 브라우저 기반 CRUD 흐름을 자세히 익힙니다.


Django CRUD 각 기능 역할


  1. ModelForm 만들기
# models.py의 필드를 자동으로 HTML 폼으로 변환
class PostForm(ModelForm):
    class Meta:
        model = Post
        fields = ['title', 'content']

DB 모델을 기반으로 입력 폼을 자동 생성해주는 역할


질문

models.py의 필드를 자동으로 HTML 폼으로 변환 class PostForm(ModelForm): class Meta: model = Post fields = ['title', 'content'] > DB 모델을 기반으로 입력 폼을 자동 생성해주는 역할 모델폼은 장고내장 함수인건가?

답변

Django 내장 클래스입니다

어디서 가져오나요?

# Django 내장 모듈에서 import
from django import forms

class PostForm(forms.ModelForm):  # Django가 제공하는 클래스 상속
    class Meta:
        model = Post
        fields = ['title', 'content']

4. Django Form / ModelForm은 왜 필요한가?

이제 본격적으로 폼을 만들기 전에, 왜 Django에서 Form 또는 ModelForm을 쓰는지 먼저 이해하고 갑니다.

초보자는 자주 이렇게 생각합니다.

HTML form 만들고 request.POST에서 값 꺼내서 저장하면 되는 거 아닌가요?

물론 기술적으로는 가능합니다. 하지만 Django는 Form을 쓰는 방식이 훨씬 체계적이고 안전합니다.

Form / ModelForm을 쓰는 이유
입력값 검증이 쉬움
에러 메시지 처리 쉬움
필드 관리가 쉬움
템플릿 렌더링이 쉬움
코드 구조가 Django 표준 흐름에 맞음
특히 ModelForm은 모델과 직접 연결되어 있어서 아주 강력합니다.

즉 아래 흐름이 가능해집니다.

Study 모델 정의
→ ModelForm 작성
→ 폼에서 입력값 검증
→ form.save()로 모델 저장
즉 ModelForm은 모델 기반 폼 자동화 도구라고 이해하면 좋습니다.


GET vs POST 차이

핵심 차이

GETPOST
용도데이터 조회데이터 전송/저장
데이터 위치URL에 노출Body에 숨겨짐
보안낮음높음
데이터 크기제한 있음제한 없음
캐싱가능불가능

눈으로 보는 차이

# GET - URL에 데이터가 보임
https://example.com/search?keyword=python&page=1

# POST - URL에 데이터가 안 보임
https://example.com/login
(아이디/비밀번호는 숨겨져서 전송)

Django에서 사용 예시

def my_view(request):

    # GET 요청 - 데이터 조회할 때
    if request.method == 'GET':
        posts = Post.objects.all()
        return render(request, 'list.html', {'posts': posts})

    # POST 요청 - 데이터 저장할 때
    if request.method == 'POST':
        form = PostForm(request.POST)
        if form.is_valid():
            form.save()  # DB 저장

질문 GET POST

GET  → 검색, 목록 조회, 상세 보기
POST → 로그인, 회원가입, 게시글 작성, 수정, 삭제

HTML 폼에서

<!-- GET 방식 -->
<form method="GET">
    <input type="text" name="keyword">
</form>

<!-- POST 방식 -->
<form method="POST">
    {% csrf_token %}  <!-- Django 보안 토큰 필수! -->
    <input type="text" name="title">
</form>

💡 조회는 GET, 변경은 POST 로 기억하세요!


질문 장고에서의 모델 폼에대한 설명과 사용쓰임방법

Django ModelForm 완벽 정리

ModelForm이란?

DB 모델(Model) + HTML 폼(Form) 을 자동으로 연결해주는 Django 내장 클래스

기본 구조

# forms.py
from django import forms
from .models import Post

class PostForm(forms.ModelForm):
    class Meta:
        model = Post          # 어떤 모델을 사용할지
        fields = ['title', 'content']  # 어떤 필드를 폼에 보여줄지
        # fields = '__all__'  # 모든 필드 사용할 때

Model 예시

# models.py
from django.db import models

class Post(models.Model):
    title = models.CharField(max_length=100)    # 제목
    content = models.TextField()                # 내용
    created_at = models.DateTimeField(auto_now_add=True)  # 생성일

CRUD별 사용 방법

✅ 생성 (Create)

# views.py
def post_create(request):
    if request.method == 'POST':
        form = PostForm(request.POST)  # 입력된 데이터 받기
        if form.is_valid():            # 유효성 검사
            form.save()                # DB 저장
            return redirect('post_list')
    else:
        form = PostForm()              # 빈 폼 생성
    return render(request, 'create.html', {'form': form})

✅ 수정 (Update)

# views.py
def post_update(request, pk):
    post = Post.objects.get(pk=pk)
    if request.method == 'POST':
        form = PostForm(request.POST, instance=post)  # 기존 데이터 불러오기
        if form.is_valid():
            form.save()               # 수정된 내용 저장
            return redirect('post_list')
    else:
        form = PostForm(instance=post)  # 기존 데이터로 폼 채우기
    return render(request, 'update.html', {'form': form})

✅ 삭제 (Delete)

# views.py
def post_delete(request, pk):
    post = Post.objects.get(pk=pk)
    if request.method == 'POST':
        post.delete()                 # DB에서 삭제
        return redirect('post_list')
    return render(request, 'delete.html', {'post': post})

HTML 템플릿에서 사용

<!-- create.html -->
<form method="POST">
    {% csrf_token %}       <!-- 보안 토큰 필수! -->
    {{ form.as_p }}        <!-- 폼 자동 렌더링 -->
    <button type="submit">저장</button>
</form>

폼 렌더링 방식 3가지

{{ form.as_p }}     <!-- <p> 태그로 감싸서 출력 -->
{{ form.as_table }} <!-- <table> 태그로 출력 -->
{{ form.as_ul }}    <!-- <ul> 태그로 출력 -->

유효성 검사

form = PostForm(request.POST)

if form.is_valid():          # 유효성 통과 ✅
    form.save()
else:
    print(form.errors)       # 어떤 오류인지 출력 ❌

fields 설정 방법

class Meta:
    model = Post
    fields = '__all__'                    # 모든 필드
    fields = ['title', 'content']         # 특정 필드만 포함
    exclude = ['created_at']              # 특정 필드만 제외

일반 Form vs ModelForm 비교

# ❌ 일반 Form - 직접 다 작성
class PostForm(forms.Form):
    title = forms.CharField()
    content = forms.CharField()
    # DB 저장도 직접 작성해야 함

# ✅ ModelForm - 자동 처리
class PostForm(forms.ModelForm):
    class Meta:
        model = Post
        fields = '__all__'
    # DB 저장은 form.save() 한 줄!

핵심 메서드 정리

메서드설명
form.is_valid()입력값 유효성 검사
form.save()DB에 저장
form.errors오류 내용 확인
form.as_p()p태그로 렌더링
instance=post기존 데이터 불러오기

💡 ModelForm = 모델 기반 자동 폼 생성 + 유효성 검사 + DB 저장 을 한번에 처리해주는 Django의 핵심 기능입니다!


질문 Django Form / ModelForm은 왜 필요하며 둘 차이점?

Django Form vs ModelForm

왜 필요한가?

HTML 폼만 사용하면 아래를 전부 직접 작성해야 함 😱

1. HTML input 태그 하나하나 작성
2. 유효성 검사 직접 작성
3. DB 저장 코드 직접 작성
4. 보안 처리 직접 작성

→ Form / ModelForm 사용하면 자동으로 해결! 😊

Django Form

# forms.py
from django import forms

class PostForm(forms.Form):
    title = forms.CharField(max_length=100)   # 직접 필드 정의
    content = forms.CharField()               # 직접 필드 정의
# views.py
def post_create(request):
    if request.method == 'POST':
        form = PostForm(request.POST)
        if form.is_valid():
            # ❌ DB 저장 코드를 직접 작성해야 함
            Post.objects.create(
                title=form.cleaned_data['title'],
                content=form.cleaned_data['content']
            )
    else:
        form = PostForm()
    return render(request, 'create.html', {'form': form})

Django ModelForm

# forms.py
from django import forms
from .models import Post

class PostForm(forms.ModelForm):
    class Meta:
        model = Post          # 모델 연결
        fields = '__all__'    # 필드 자동 생성
# views.py
def post_create(request):
    if request.method == 'POST':
        form = PostForm(request.POST)
        if form.is_valid():
            form.save()       # ✅ 한 줄로 DB 저장
    else:
        form = PostForm()
    return render(request, 'create.html', {'form': form})

핵심 차이점

FormModelForm
필드 정의직접 작성모델에서 자동 생성
DB 저장직접 작성form.save() 한 줄
모델 연결❌ 없음✅ 자동 연결
코드량많음적음
유효성 검사✅ 가능✅ 가능
사용 상황DB 불필요한 폼DB 연동 필요한 폼

언제 무엇을 쓰나요?

✅ Form 사용
- 로그인 (DB 저장 없이 검증만)
- 검색 폼
- 이메일 문의 폼
- DB와 관계없는 데이터 처리

✅ ModelForm 사용
- 게시글 작성/수정
- 회원가입
- 댓글 작성
- DB에 저장이 필요한 모든 것

한눈에 비교

# Form - 검색 폼 예시 (DB 저장 X)
class SearchForm(forms.Form):
    keyword = forms.CharField()

# ModelForm - 게시글 폼 (DB 저장 O)
class PostForm(forms.ModelForm):
    class Meta:
        model = Post
        fields = '__all__'

💡 DB 저장이 필요하면 ModelForm, 아니면 Form!
ModelForm은 Form의 기능을 모두 포함하면서 DB 연동까지 자동으로 해줍니다.


중요 질문 답변

1편 순서기억 이해
Form / ModelForm을 쓰는 이유
나의질문 폼이랑 모델폼차이가 이해가 안되신다는건가용??
Study 모델 정의
→ ModelForm 작성
→ 폼에서 입력값 검증
→ form.save()로 모델 저장

답변
스터디 모델을 1편에서 만들었잖아요?
그 모델이랑 연결되는 form을 만들라는거에용
모델과 연관성있는 것 무언가 입력을 받는 구조의 폼이라고 생각

Form은
그냥 입력창을 만드는 도구
어떤 값을 받을지 직접 다 적어줘야 함
저장도 직접 해야 함

즉, “입력만 받는 일반 양식”이라고 이해하시면 됩니다.

ModelForm은
모델을 기준으로 폼을 쉽게 만드는 도구
모델 필드를 바탕으로 입력창을 만들 수 있음
검증도 도와주고, form.save()로 DB 저장도 쉬움

즉, “모델이랑 연결된 폼”이라고 이해하시면 됩니다.

우리가 템플릿에서 보는

태그는
사용자가 값을 입력해서 보내는 HTML 영역이에요!
사용자가 입력한 값이 서버로 전달되면,
서버에서 ModelForm이 그 값을 받아 검증하고,
문제가 없으면 저장한다고 생각하시면 됩니당

나의질문
study 앱에 폼을 만들고 그 폼이라는것은 그냥 앱 생성할때마다 만드는 폼이라고 생각하면되나요.. 그리고 그안에 CRUS페이지까지 스터디앱에 만드는거죠?

답변
폼은 앱 만들 때 무조건 만드는 게 아니라, 사용자의 입력을 받아야 할 때 만드는 거예요! 항상 만드는건 아니에용 그리고 Study 앱을 만들었으니까, Study 관련 CRUD 페이지도 그 앱 안에서 같이 만듭니다

Form vs ModelForm 적용 범위
아니요, 둘 다 모델 파일과 독립적으로 사용할 수 있습니다.

forms.Form — 모델과 무관
class ContactForm(forms.Form):
name = forms.CharField()
email = forms.EmailField()
message = forms.CharField(widget=forms.Textarea)
모델 없이 순수하게 입력값 처리/검증만 할 때 사용
예: 문의 폼, 검색 폼, 로그인 폼, 계산기 폼 등
forms.ModelForm — 모델과 연결됨
class StudyForm(forms.ModelForm):
class Meta:
model = Study # ← 특정 모델에 종속
fields = [...]
반드시 Meta.model에 연결할 모델이 필요
form.save()로 DB에 바로 저장 가능
정리
구분 모델 필요 여부 DB 저장
forms.Form ❌ 불필요 직접 처리해야 함
forms.ModelForm ✅ 필수 form.save()로 자동
즉, ModelForm만 모델 파일에 해당되고, Form은 모델 없이 어디서든 독립적으로 사용할 수 있습니다.

  1. forms.Form이 필요한 때
    모델에 저장할 필요 없이 입력값만 처리할 때 사용합니다.

예시 1 - 검색 폼
class SearchForm(forms.Form):
keyword = forms.CharField()

# 검색어를 받아서 필터링만 할 뿐, DB에 저장 안 함

예시 2 - 로그인 폼
class LoginForm(forms.Form):
username = forms.CharField()
password = forms.CharField(widget=forms.PasswordInput)

# 인증만 하고 저장 X

예시 3 - 문의/이메일 폼
class ContactForm(forms.Form):
email = forms.EmailField()
message = forms.CharField()

# 이메일로 전송만 하고 저장 X
  1. "메서드"라는 표현에 대해
    정확히는 구분해서 불러야 합니다.

용어 설명 예시
클래스(Class) 설계도 전체 StudyForm, LoginForm
메서드(Method) 클래스 안의 함수 clean_minutes(), save()
필드(Field) 클래스 안의 변수/속성 title, email
class StudyForm(forms.ModelForm): # ← 클래스

title = forms.CharField()      # ← 필드

def clean_minutes(self):       # ← 메서드
    ...

그래서

StudyForm 자체 → 클래스
clean_minutes() → 메서드
forms.Form, forms.ModelForm → 클래스를 상속받는 것
"Form이랑 ModelForm 메서드야?" 라고 하면 엄밀히는 클래스라고 표현하는 게 맞습니다.


5. ModelForm 만들기

이제 실제로 Study 모델과 연결되는 StudyForm을 만듭니다.

ModelForm이 자동으로 해주는 것

기능설명
필드 자동 생성모델의 필드를 자동으로 HTML <input>으로 변환
유효성 검사입력값이 올바른지 자동 검증
DB 저장.save() 한 줄로 DB에 바로 저장

직접 만들 때 vs ModelForm 비교

# ❌ 직접 만들 때 (길고 복잡)
<input type="text" name="title">
<input type="text" name="content">
# 유효성 검사도 직접 작성...
# DB 저장도 직접 작성...

# ✅ ModelForm 사용 (간단!)
form = PostForm()  # 끝!
form.save()        # DB 저장도 한 줄!

결론

Django 내장 클래스 ✅
별도 설치 불필요 ✅
from django import forms 로 바로 사용 가능 ✅

💡 Django가 반복적인 폼 작업을 자동화해주기 위해 만든 강력한 내장 기능입니다!


2. 생성 (Create)

사용자가 폼에 데이터 입력 → DB에 새 데이터 저장
예) 게시글 작성, 회원가입

새로운 데이터를 추가하는 기능


3. 상세 (Detail)

목록에서 항목 클릭 → 해당 데이터 상세 내용 표시
예) 게시글 본문 보기

특정 데이터 하나를 자세히 조회하는 기능


4. 수정 (Update)

기존 데이터를 불러와 폼에 표시 → 수정 후 저장
예) 게시글 편집

기존 데이터를 변경하는 기능


5. 삭제 (Delete)

특정 데이터 선택 → DB에서 완전 삭제
예) 게시글 삭제

데이터를 DB에서 제거하는 기능


6. 페이지네이션 (Pagination)

데이터가 많을 때 → 한 페이지에 n개씩 나눠서 표시
예) 1페이지, 2페이지, 3페이지...

많은 데이터를 나눠서 보여주는 기능


전체 흐름 요약

ModelForm        → 입력 폼 자동 생성
Create (생성)    → 데이터 추가 (INSERT)
Detail (상세)    → 데이터 1개 조회 (SELECT)
Update (수정)    → 데이터 변경 (UPDATE)
Delete (삭제)    → 데이터 제거 (DELETE)
Pagination       → 데이터 분할 표시

💡 이 6가지가 합쳐지면 브라우저 기반 CRUD 완성입니다!


왜 이 순서인가?

이 순서는 기능을 그냥 나열한 것이 아닙니다.

예를 들어:

폼이 있어야 생성/수정 기능을 만들 수 있습니다.
상세 페이지가 있어야 수정/삭제 이후 이동 흐름도 자연스러워집니다.
CRUD가 어느 정도 끝나야 페이지네이션을 실제로 체감할 수 있습니다.
즉 이번 교안도 여전히 실제 실습 순서 기준으로 설계되어 있습니다.


2번 하기전 준비



6. 생성(Create) 기능을 만들기 전에 URL부터 추가하기


path() 구조 분석
pythonpath('', views.study_list, name='list')
path(경로, 뷰함수, name=이름) — 총 3개의 인자로 구성됩니다.

1. form.save() 한 줄로 저장되는 이유

쉽게 비유하면:

일반 Form    = 그냥 빈 종이
ModelForm   = Study 모델과 연결된 자동완성 종이
# ModelForm은 이미 내부에 이런 동작이 내장되어 있음
class StudyForm(forms.ModelForm):
    class Meta:
        model = Study          # ← "나는 Study랑 연결됐어"
        fields = ['title', ...] # ← "이 필드들을 저장해"

# 그래서 form.save() 한 줄이
# 내부적으로 이걸 자동으로 해줌
study = Study(
    title = form.cleaned_data['title'],
    category = form.cleaned_data['category'],
    ...
)
study.save()  # DB 저장

form.save() = "연결된 모델에 알아서 넣고 저장해줘" 라는 명령


2. 코드 구조 정체

from django.shortcuts import redirect, render  # ← 임포트
from .forms import StudyForm                   # ← 임포트
from .models import Study                      # ← 임포트

import = 다른 파일에서 필요한 것만 가져오는 것

  • from 어디서 import 무엇을

def study_list(request):   # ← 함수
    ...
    return render(...)

def study_create(request): # ← 함수
    ...
    return render(...)

def = 함수입니다 (메서드 아님)

구분위치예시
함수클래스 밖에 독립적으로 존재def study_list(request)
메서드클래스 안에 존재def clean_minutes(self)

def study_create(request):
    form = StudyForm(request.POST or None)

    if request.method == 'POST' and form.is_valid():
        form.save()
        return redirect('study:list')   # ← if 안의 return

    return render(request, 'study/study_form.html', {...})  # ← 함수의 return

return이 2개인 이유

사용자가 처음 페이지 접속 (GET 요청)
    → if 조건 False → 아래 render() 실행 → 폼 화면 보여줌

사용자가 폼 작성 후 제출 (POST 요청)
    → if 조건 True → form.save() → redirect로 목록으로 이동

전체 구조 한눈에

# 1. 임포트 (재료 가져오기)
from django.shortcuts import redirect, render

# 2. 함수 정의 (클래스 밖 → 함수)
def study_create(request):

    # 3. 변수 선언
    form = StudyForm(request.POST or None)

    # 4. 조건 분기
    if request.method == 'POST' and form.is_valid():
        form.save()
        return redirect('study:list')  # POST면 여기서 끝

    return render(...)  # GET이면 여기서 끝

핵심: def클래스 밖에 있으면 → 함수, 클래스 안에 있으면 → 메서드


7. 생성(Create) View 작성

어려움

이제 study_create View를 추가합니다.


8. 생성 / 수정 공용 폼 템플릿 만들기


HTML 템플릿 큰 그림 분석


1. 상속 구조

{% extends 'base.html' %}
  • 이 파일은 base.html부모로 삼음
  • 즉, base.html의 공통 레이아웃(헤더, 푸터 등)을 그대로 가져오고
  • 다른 부분만 여기서 채워 넣는 구조

2. block 2개

{% block title %}
    {{ page_title }} | 공부시간 기록기
{% endblock %}

{% block content %}
    ... 실제 내용 ...
{% endblock %}
  • block = base.html에 뚫어놓은 구멍
  • 이 파일이 그 구멍을 채워넣는 역할
  • title → 브라우저 탭 제목
  • content → 실제 화면에 보이는 내용 전체

3. content 안 구조

{% block content %}
    │
    ├── section.hero-card       ← 상단 소개 영역
    │       제목, 설명글
    │
    └── section.content-card    ← 실제 폼 영역
            form

hero-card (소개 영역)

<section class="hero-card">
    <span>Study Form</span>          <!-- 작은 라벨 -->
    <h1>{{ page_title }}</h1>        <!-- 큰 제목 (views.py에서 전달) -->
    <p>오늘의 공부를 구체적으로...</p> <!-- 설명글 -->
</section>

content-card (폼 영역)

<section class="content-card">
    <form method="post">
        {% csrf_token %}   <!-- 보안 토큰 -->

        공부 제목
        카테고리
        공부 날짜
        시간 / 분       ← 이 둘은 나란히 배치 (inline-2)
        메모

        저장하기 버튼 / 목록으로 버튼
    </form>
</section>

4. 폼 필드 패턴 (반복구조)

모든 필드가 똑같은 패턴으로 반복됩니다

<div class="form-row">

    <!-- 라벨 -->
    <label for="{{ form.title.id_for_label }}">
        {{ form.title.label }}
    </label>

    <!-- 입력창 -->
    {{ form.title }}

    <!-- 에러 메시지 (있을 때만 표시) -->
    {% if form.title.errors %}
        {{ form.title.errors }}
    {% endif %}

</div>
부분역할
label입력창 설명 텍스트
{{ form.title }}실제 input 태그 렌더링
form.title.errors검증 실패시 에러 출력

5. 특이한 부분 2가지

① 시간/분 나란히 배치

<div class="form-row inline-2">
    <div> 시간 입력 </div>
    <div> 분 입력 </div>
</div>
  • inline-2 클래스로 두 개를 가로로 나란히 배치

② 보안 토큰

<form method="post">
    {% csrf_token %}
  • POST 요청시 반드시 필요
  • 없으면 Django가 요청을 거부
  • 외부에서 악의적인 요청을 막는 보안 장치

전체 흐름 한줄 요약

base.html 레이아웃 상속
    → 소개 영역 (hero-card)
    → 폼 영역 (content-card)
        → 필드마다 라벨 + 입력창 + 에러메시지 패턴 반복
        → 저장 or 목록으로 버튼

9. CSS에 폼 관련 스타일 추가하기


10. 브라우저에서 생성 기능 먼저 확인하기


11. 상세(Detail) 기능을 만들기 전에 URL 추가하기


12. 상세(Detail) View 작성


13. 상세 페이지 템플릿 만들기


14. 목록 페이지에 상세 보기 링크 연결하기

profile
개발언어를 배우는 과정 기록

0개의 댓글