| ํ์ผ | ์ญํ |
|---|---|
| manage.py | Django ๋ช ๋ น ์คํ ์ง์ ์ |
| config/settings.py | ํ๋ก์ ํธ ์ ์ฒด ์ค์ ํ์ผ |
| config/urls.py | ์ต์์ URL ์ฐ๊ฒฐ ํ์ผ |
| config/wsgi.py | ๋ฐฐํฌ์ฉ ์๋ฒ ์ฐ๊ฒฐ |
| config/asgi.py | ๋น๋๊ธฐ ์๋ฒ ์ฐ๊ฒฐ |
manage ๊ด๋ฆฌํ๋ค
config ๊ตฌ์ฑ
setting ํ๊ฒฝ
์ด์ Django ํ๋ก์ ํธ ์์ฒด๋ฅผ ์์ฑํฉ๋๋ค.
django-admin startproject config .
terminal
์ด ๋ช
๋ น์ด์ ์๋ฏธ
์ด๋ณด์ ์
์ฅ์์๋ ์ด ๋ช
๋ น์ด๊ฐ ์กฐ๊ธ ๋ฏ์ค ์ ์์ต๋๋ค.
startproject config .
config ๋ Django ์ค์ ํจํค์ง ์ด๋ฆ (๋ณดํต ์์
๋ mysite๋ก ์์ฑํ์์ต๋๋ค!)
๋ง์ง๋ง . ์ โํ์ฌ ํด๋์ ๋ฐ๋ก ์์ฑํ๋ผโ๋ ๋ป
์
๋๋ค.
์ฆ ์ง๊ธ ์์ ์ค์ธ study_time_tracker ํด๋ ์์ Django ํ๋ก์ ํธ๋ฅผ ๋ฐ๋ก ์์ฑํ๊ฒ ๋ค๋ ์๋ฏธ์ ๋๋ค.
์์ฑ ํ ๊ตฌ์กฐ
study_time_tracker/
โโโ .venv/
โโโ config/
โ โโโ init.py
โ โโโ asgi.py
โ โโโ settings.py
โ โโโ urls.py
โ โโโ wsgi.py
โโโ manage.py
Django์์๋ ๊ธฐ๋ฅ ๋จ์๋ฅผ ์ฑ(App) ์ผ๋ก ๋๋์ด ๊ด๋ฆฌํฉ๋๋ค.
์ด๋ฒ ์ค์ต์์๋ ๊ณต๋ถ ๊ธฐ๋ก ๊ธฐ๋ฅ์ ๋ด๋นํ study ์ฑ์ ์์ฑํฉ๋๋ค.
python manage.py startapp study
์์ฑ ํ ๊ตฌ์กฐ๋ ์๋์ ๋น์ทํฉ๋๋ค.
study/
โโโ init.py
โโโ admin.py
โโโ apps.py
โโโ migrations/
โโโ models.py
โโโ tests.py
โโโ views.py
dir ๋ํํ ๋ฆฌ
contrib ๊ธฐ์ฌํ๋ค
auth ์ธ์ฆ
contenttypes ์ฝํ
์ธ ์ ํ
staticfiles ์ ์ ํ์ผ
insecure ๋ถ์์ ํ
ALLOWED_HOSTS ํ์ฉ๋ ํธ์คํธ
MIDDLE WARE ์ค๊ฐ ์ ํ?
security ๋ณด์
common ํํ
Authentication ์
์ฆ
context ๋ฌธ๋งฅ
process ์งํ
request ์๊ตฌ
template ๋ณด๋ฐ์ด
APPLICATION ์ ์ฒญ ์ ์ฉ ์์
'config ๊ตฌ์ฑ
'default ๊ธฐ๋ณธ ๋ํดํธ๊ฐ
'ENGINE ๊ธฐ๊ด ์ฐจ ์๋จ
VALIDATORS ๊ฒ์ฆ์
AUTH_PASSWORD_VALIDATORS ์ธ์ฆ ๋น๋ฐ๋ฒํธ ๊ฒ์ฆ์
validation ํ์ธ
User ์ฌ์ฉ์
Attribute
Similarity ์ ์ฌ์ฑ
Attribute ์์ฑ
Validator ๊ฒ์ฆ์ธ
Minimum ์ต์ํ์
Length ๊ธธ์ด
Validator ๊ฒ์ฆ์ธ
CommonPasswordValidator ์ผ๋ฐ ๋น๋ฐ๋ฒํธ ์ ํจ์ฑ ๊ฒ์ฌ๊ธฐ
NumericPasswordValidator ์ซ์ ๋น๋ฐ๋ฒํธ ์ ํจ์ฑ ๊ฒ์ฌ๊ธฐ
LANGUAGE_CODE ์ธ์ด ์ฝ๋
TIME_ZONE ์๊ฐ๋
STATICFILES ์ ์ ํ์ผ
FIELD ๋ถ์ผ


--> ๊ธฐ๋ณธ์ ์ธ ๊ธฐ์ด์ ์ธ ๊ฐ๋ ์ด ํ์.



CATEGORY ๋ฒ์ฃผ
algorithm ์ฐ์ฐ
verbose ๋ง ์๊ฐ ๋ง์
PositiveInteger ์์ ์ ์
ordering ์ฃผ๋ฌธ
verbose_name
plural ๋ณต์์
return ๋ฐํํ๋ค
property ์ฌ์ฐ ์์ ํ๋ค
import ์์
blank ๊ณต๋ฐฑ
๋ชจ๋ธ์ ์ค๊ณํ ๋๋ ์ฝ๋๋ณด๋ค "์ด ์๋น์ค๊ฐ ๊ธฐ์ตํด์ผ ํ ์ ๋ณด๊ฐ ๋ญ๊ฐ?" ๋ฅผ ๋จผ์ ์๊ฐํฉ๋๋ค.
๊ณต๋ถ ๊ธฐ๋ก ์ฑ์ด ๊ธฐ์ตํด์ผ ํ ๊ฒ๋ค์ ๋ฉ๋ชจ์ง์ ์ ๋ฏ์ด ๋์ด
โ ๋ฌด์จ ๊ณต๋ถ๋ฅผ ํ๋? (title)
โ ์ด๋ค ์นดํ
๊ณ ๋ฆฌ์ธ๊ฐ? (category)
โ ์ธ์ ๊ณต๋ถํ๋? (study_date)
โ ๋ช ์๊ฐ ํ๋? (hours / minutes)
โ ๋ฉ๋ชจํ ๊ฒ ์๋? (memo)
โ ์ธ์ ์ด ๊ธฐ๋ก์ ๋ง๋ค์๋? (created_at)
โ ๋ง์ง๋ง์ผ๋ก ์์ ํ ๊ฑด? (updated_at)
์ด๋ ๊ฒ ์์ฐ์ด๋ก ๋จผ์ ๋์ดํ ๋ค์, ๊ฐ ํญ๋ชฉ์ ๋ง๋ ํ๋ ํ์ ์ ๊ณจ๋ผ ์ฝ๋๋ก ์ฎ๊ธฐ๋ ์์์ ๋๋ค.

CATEGORY_CHOICESCATEGORY_CHOICES = [
('python', 'Python'),
('django', 'Django'),
]
# ('DB์ ์ ์ฅ๋๋ ๊ฐ', 'ํ๋ฉด์ ๋ณด์ด๋ ๊ฐ')
# DB์ 'python' ์ ์ฅ, ์ฌ์ฉ์ ๋์ 'Python' ํ์
title = models.CharField(max_length=200, verbose_name='๊ณต๋ถ ์ ๋ชฉ')
# โ ์ต๋ 200์ โ admin์ ํ์๋ ์ด๋ฆ
category = models.CharField(
max_length=30,
choices=CATEGORY_CHOICES, # โ ์์์ ๋ง๋ ์ ํ์ง ์ฐ๊ฒฐ
default='django', # โ ๊ธฐ๋ณธ๊ฐ
)
study_date = models.DateField(verbose_name='๊ณต๋ถ ๋ ์ง')
# ๋ ์ง๋ง ์ ์ฅ (2026-03-12)
hours = models.PositiveIntegerField(default=0)
# 0 ์ด์์ ์ ์๋ง ํ์ฉ
memo = models.TextField(blank=True)
# ๊ธด ๊ธ, ์ ํ ์
๋ ฅ
created_at = models.DateTimeField(auto_now_add=True)
# ์ฒ์ ์ ์ฅํ ๋ ์๋์ผ๋ก ํ์ฌ ์๊ฐ ๊ธฐ๋ก, ์ดํ ๋ณ๊ฒฝ ์ ๋จ
updated_at = models.DateTimeField(auto_now=True)
# ์ ์ฅํ ๋๋ง๋ค ์๋์ผ๋ก ํ์ฌ ์๊ฐ์ผ๋ก ๊ฐฑ์
class Meta:
ordering = ['-study_date', '-created_at']
# ์กฐํ ์ ์ต์ ๋ ์ง์ ์๋ ์ ๋ ฌ (- = ๋ด๋ฆผ์ฐจ์)
__str__def __str__(self):
return f'{self.title} ({self.study_date})'
# admin ํ์ด์ง๋ shell์์ ๊ฐ์ฒด๋ฅผ ์ถ๋ ฅํ๋ฉด
# "Django ORM ๋ณต์ต (2026-03-12)" ํํ๋ก ๋ณด์
@property@property
def total_minutes(self):
return self.hours * 60 + self.minutes
# DB์ ์ ์ฅ ์ ํจ. ๊ทธ๋ฅ ๊ณ์ฐํด์ ๋๋ ค์ฃผ๋ ๊ฐ
# study.total_minutes โ 150 (2์๊ฐ 30๋ถ)
1๋จ๊ณ ๊ธฐ์ตํด์ผ ํ ์ ๋ณด๋ฅผ ์์ฐ์ด๋ก ๋์ด
"์ ๋ชฉ, ๋ ์ง, ์๊ฐ, ๋ฉ๋ชจ..."
2๋จ๊ณ ๊ฐ ์ ๋ณด์ ๋ง๋ ํ๋ ํ์
์ ํ
๊ธ์ โ CharField / TextField
์ซ์ โ IntegerField
๋ ์ง โ DateField
3๋จ๊ณ ๊ฐ ํ๋์ ์ต์
์ถ๊ฐ
ํ์์ธ์ง? ๊ธฐ๋ณธ๊ฐ์? ์ต๋ ๊ธธ์ด๋?
4๋จ๊ณ Meta, __str__, property ์ถ๊ฐ
์ ๋ ฌ ๋ฐฉ์, ํ์ ์ด๋ฆ, ๊ณ์ฐ ์์ฑ
์ด ์์๋ก ์๊ฐํ๋ฉด ์ด๋ค ๋ชจ๋ธ์ด๋ ๋งํ์ง ์๊ณ ์์ฑํ ์ ์์ด์! ๋ ๊ถ๊ธํ ๋ถ๋ถ ์์ผ๋ฉด ์๋ ค์ฃผ์ธ์ ๐
CharField๋ Django ๋ชจ๋ธ์์ ๊ฐ์ฅ ์์ฃผ ์ฐ๋ ํ๋ ์ค ํ๋๋ก, ์งง์ ํ
์คํธ๋ฅผ ์ ์ฅํ๋ ์นธ์
๋๋ค. ์ด๋ฆ, ์ ๋ชฉ, ์ฃผ์์ฒ๋ผ ํ ์ค์ง๋ฆฌ ๊ธ์๋ฅผ ๋ด์ ๋ ์๋๋ค.
์๋ ํ๋ฆ๋๋ก ์ ์ฒด ๊ฐ๋ ์ ํ๋์ ํ์ธํด ๋ณด์ธ์.---

์์ ์ ์ ํ๋๋ผ๊ณ ์๊ฐํ๋ฉด ์ฌ์์. ์ด๋ฆ, ์ ๋ชฉ, ๋ธ๋๋๋ช ์ฒ๋ผ ํ ์ค์ง๋ฆฌ ํ ์คํธ๋ฅผ ๋ด๋ ์ฉ๋์ ๋๋ค.
name = models.CharField(max_length=100)
์ด ํ ์ค์ด DB์ VARCHAR(100) ์ปฌ๋ผ ํ๋๋ฅผ ๋ง๋ค์ด ์ค๋๋ค.
| ์ต์ | ์ญํ | ์์ |
|---|---|---|
max_length | ์ต๋ ๊ธ์ ์ (ํ์!) | max_length=100 |
blank=True | ํผ์์ ๋น์๋ ๋จ | ์ ํ ์ ๋ ฅ ํญ๋ชฉ์ ์ฌ์ฉ |
null=True | DB์ NULL ์ ์ฅ ํ์ฉ | blank์ ํจ๊ป ์ธ ๋๊ฐ ๋ง์ |
default='' | ๊ธฐ๋ณธ๊ฐ ์ค์ | ์๋ฌด๊ฒ๋ ์ ์ ๋ ฅํ๋ฉด ์ด ๊ฐ |
blank์null์ ์ฐจ์ด๊ฐ ํท๊ฐ๋ฆด ์ ์๋๋ฐ,blank๋ "ํผ ์ ๋ ฅ ๊ฒ์ฆ",null์ "DB ์ ์ฅ" ์ ๋ฌธ์ ์ ๋๋ค.
TextField ์จ์ผ ํ ๋: ๊ฒ์๊ธ ๋ณธ๋ฌธ, ๋ฆฌ๋ทฐ ๋ด์ฉ์ฒ๋ผ ๊ธธ๊ณ ์ ํ ์๋ ํ
์คํธIntegerField ์จ์ผ ํ ๋: ๋์ด, ๊ฐ๊ฒฉ์ฒ๋ผ ์ซ์๊ถ๊ธํ ์ต์ ์ด ์์ผ๋ฉด ๋ค์ด์ด๊ทธ๋จ์ ๊ฐ ๋ฐ์ค๋ฅผ ํด๋ฆญํด ๋ ๋ฌผ์ด๋ณผ ์ ์์ด์! ๐
CharField blank ์ต์ ์ด ๋ญ๊ฐ์?
blank=True ์ต์
์ด๋?blank๋ ํผ(Form) ์
๋ ฅ ์ ์ด ์นธ์ ๋น์๋ ๋๋์ง ๋ฅผ ๊ฒฐ์ ํ๋ ์ต์
์
๋๋ค.
ํ์๊ฐ์ ํ์ด์ง๋ฅผ ๋ ์ฌ๋ ค๋ณด์ธ์.
- ์ด๋ฆ ์ ๋ ฅ์นธ โ ํ์ (๋น์ฐ๋ฉด "์ด๋ฆ์ ์ ๋ ฅํด์ฃผ์ธ์" ์ค๋ฅ)
- ๋๋ค์ ์ ๋ ฅ์นธ โ ์ ํ (๋น์๋ ํต๊ณผ)
์ด "์ ํ ์นธ"์ ๋ง๋ค ๋
blank=True๋ฅผ ์๋๋ค.
class User(models.Model):
username = models.CharField(max_length=50)
# blank ์์ = ๊ธฐ๋ณธ๊ฐ์ด blank=False
# โ ํผ์์ ๋ฐ๋์ ์
๋ ฅํด์ผ ํจ
nickname = models.CharField(max_length=50, blank=True)
# โ ํผ์์ ๋น์๋ ํต๊ณผ๋จ
blank vs null ์ฐจ์ด (์์ฃผ ํท๊ฐ๋ฆฌ๋ ๋ถ๋ถ!)| ์ต์ | ์ธ์ ์๋ํ๋? | ์ญํ |
|---|---|---|
blank=True | ํผ ์ ๋ ฅํ ๋ | "์ด ์นธ ์ ์ฑ์๋ ๋ฉ๋๋ค" |
null=True | DB์ ์ ์ฅํ ๋ | "DB์ NULL ๊ฐ ์ ์ฅ ํ์ฉ" |
CharField๋ ๋ณดํต null=True ์์ด blank=True๋ง ์จ๋ ์ถฉ๋ถํฉ๋๋ค. ๋น์ด์์ ๋ DB์ NULL ๋์ ๋น ๋ฌธ์์ด ''์ ์ ์ฅํ๊ธฐ ๋๋ฌธ์
๋๋ค.
# CharField ๊ถ์ฅ ํจํด
nickname = models.CharField(max_length=50, blank=True, default='')
# โ ํผ ๋น์๋ ๋จ โ ๋น ๋ฌธ์์ด๋ก ์ ์ฅ
blank=True= "์ด ํญ๋ชฉ์ ์ ํ ์ ๋ ฅ์ ๋๋ค" ๋ผ๊ณ Django์๊ฒ ์๋ ค์ฃผ๋ ๊ฒ
์ถ๊ฐ๋ก ๊ถ๊ธํ ์ต์ ์์ผ๋ฉด ์๋ ค์ฃผ์ธ์! ๐
CharField null ์ต์ ์ด ๋ญ๊ฐ์?
null=True ์ต์
์ด๋?null์ DB(๋ฐ์ดํฐ๋ฒ ์ด์ค)์ ์ ์ฅํ ๋ "๊ฐ ์์"์ NULL๋ก ์ ์ฅํ ์ง ๋ฅผ ๊ฒฐ์ ํ๋ ์ต์
์
๋๋ค.
์์ ์ ์ ๋ ์ฌ๋ ค๋ณด์ธ์.
- ์ ์ ๋น ๋ฌธ์์ด
''์ ์ฅ โ ์ ์ด ์กด์ฌํ๋๋ฐ ๋ด์ฉ์ด ์๋ ๊ฒ- ์ ์ NULL ์ ์ฅ โ ์ ์์ฒด์ "์๋ฌด ๊ฐ๋ ์์" ํ์
์ด ๋ ๊ฐ์ง๋ DB ์ ์ฅ์์ ๋ค๋ฅธ ๊ฐ์ ๋๋ค.
class User(models.Model):
nickname = models.CharField(max_length=50, blank=True)
# null=True ์์ โ ๋น์ด์์ผ๋ฉด DB์ '' (๋น ๋ฌธ์์ด) ์ ์ฅ
bio = models.CharField(max_length=200, blank=True, null=True)
# null=True ์์ โ ๋น์ด์์ผ๋ฉด DB์ NULL ์ ์ฅ
| ์ํฉ | null=True ์์ ๋ | null=True ์์ ๋ |
|---|---|---|
| ๋๋ค์ ์ ๋ ฅ ์ ํจ | '' (๋น ๋ฌธ์์ด) | NULL |
| ๋๋ค์ ์ ๋ ฅํจ | 'heeyoung' | 'heeyoung' |
blank vs null ํ๋์ ๋น๊ตblank=True โ ํผ(ํ๋ฉด) ๋จ๊ณ์์ ์๋ โ "์
๋ ฅ ์ ํด๋ ๋จ"
null=True โ DB ์ ์ฅ ๋จ๊ณ์์ ์๋ โ "NULL๋ก ์ ์ฅ ํ์ฉ"
์ฌ์ฉ์๊ฐ ํผ์ ์๋ฌด๊ฒ๋ ์ ์
๋ ฅ
โ
blank=True? โโโ No โโโ "ํ์ ํญ๋ชฉ์
๋๋ค" ์ค๋ฅ ๋ฐ์
โ
Yes
โ
DB์ ์ ์ฅํ ๋
null=True? โโโ No โโโ '' (๋น ๋ฌธ์์ด) ๋ก ์ ์ฅ
โ
Yes
โ
NULL ๋ก ์ ์ฅ
CharField๋ null=True๋ฅผ ๋๋๋ก ์ฐ์ง ์๋ ๊ฒ์ด Django ๊ถ์ฅ ๋ฐฉ์์
๋๋ค. "๊ฐ ์์"์ ํํํ๋ ๋ฐฉ๋ฒ์ด NULL๊ณผ '' ๋ ๊ฐ์ง๊ฐ ์๊ฒจ์ ๋์ค์ ์กฐํํ ๋ ํผ๋์ค๋ฝ๊ธฐ ๋๋ฌธ์
๋๋ค.
# ๊ถ์ฅ
nickname = models.CharField(max_length=50, blank=True, default='')
# ๋น๊ถ์ฅ (CharField์์)
nickname = models.CharField(max_length=50, blank=True, null=True)
null=True๋CharField๋ณด๋คIntegerField,DateField๊ฐ์ ์ซ์/๋ ์ง ํ๋์์ ๋ ์์ฐ์ค๋ฝ๊ฒ ์๋๋ค. ์ซ์ ํ๋๋ "๊ฐ ์์"์0์ผ๋ก ํํํ๋ฉด ์๋ฏธ๊ฐ ๋ฌ๋ผ์ง๊ธฐ ๋๋ฌธ์ ๋๋ค.
null=True= "์ด ์นธ์ด ๋น์ด์์ ๋ DB์ NULL๋ก ์ ์ฅํด๋ ๋ฉ๋๋ค" ๋ผ๊ณ Django์๊ฒ ์๋ ค์ฃผ๋ ๊ฒ
๊ถ๊ธํ ๊ฒ ์์ผ๋ฉด ๋ ๋ฌผ์ด๋ณด์ธ์! ๐
CharField max_length ์ต์ ์ด ๋ญ๊ฐ์?
max_length ์ต์
์ด๋?max_length๋ ์ด ์นธ์ ์
๋ ฅํ ์ ์๋ ์ต๋ ๊ธ์ ์๋ฅผ ์ ํ๋ ์ต์
์
๋๋ค. CharField์์ ๋ฐ๋์ ์จ์ผ ํ๋ ํ์ ์ต์
์
๋๋ค.
์ข ์ด ์๋ฅ์ ์ ๋ ฅ์นธ์ ๋ ์ฌ๋ ค๋ณด์ธ์.
- ์ด๋ฆ ์นธ โ
[ _ _ _ _ _ _ _ _ _ _ ](10์นธ)- ์ฃผ์ ์นธ โ
[ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ ](20์นธ)
max_length๋ ์ด ์นธ์ ํฌ๊ธฐ๋ฅผ ์ ํ๋ ๊ฒ์ ๋๋ค.
class User(models.Model):
username = models.CharField(max_length=50)
# ์ต๋ 50๊ธ์๊น์ง๋ง ์ ์ฅ ๊ฐ๋ฅ
email = models.CharField(max_length=200)
# ์ต๋ 200๊ธ์๊น์ง ์ ์ฅ ๊ฐ๋ฅ
max_length=50 ์ค์ ์
โ DB ํ
์ด๋ธ ์์ฑํ ๋
โ VARCHAR(50) ์ปฌ๋ผ์ผ๋ก ๋ง๋ค์ด์ง
โ DB ์์ฒด์์ 50์ ์ด๊ณผ ์ ์ฅ ์ฐจ๋จ
โก ํผ(ํ๋ฉด) ์
๋ ฅํ ๋
โ 51์ ์ด์ ์
๋ ฅํ๋ฉด "์ด ํ๋์ ์ต๋ ๊ธธ์ด๋ 50์
๋๋ค" ์ค๋ฅ ๋ฐ์
โ Django๊ฐ ์๋์ผ๋ก ๊ฒ์ฆํด์ค
| ์ ์ฅํ ๋ด์ฉ | ๊ถ์ฅ ๊ฐ | ์ด์ |
|---|---|---|
| ์ด๋ฆ, ๋๋ค์ | 50 | ๋๋ถ๋ถ 50์ ์ด๋ด |
| ์ด๋ฉ์ผ ์ฃผ์ | 200 | ์ด๋ฉ์ผ ์ต๋ ๊ธธ์ด ๊ท๊ฒฉ |
| ์ ๋ชฉ, ์ํ๋ช | 100~200 | ์ฌ์ ์๊ฒ ์ค์ |
| ์ฃผ์ | 255 | ๊ธด ์ฃผ์ ๋๋น |
| ๋น๋ฐ๋ฒํธ(ํด์) | 128 | ์ํธํ๋ ๋ฌธ์์ด ๊ธธ์ด |
๊ธด ๊ธ(๊ฒ์๊ธ ๋ณธ๋ฌธ, ๋ฆฌ๋ทฐ ๋ด์ฉ ๋ฑ)์
max_length๊ฐ ์๋TextField๋ฅผ ์ฐ๋ ๊ฒ ๋ง์ต๋๋ค.
# ์ด๋ ๊ฒ ์ฐ๋ฉด ์ค๋ฅ ๋ฐ์!
name = models.CharField()
# Django๊ฐ ์ด๋ ๊ฒ ์๋ ค์ค:
# TypeError: CharField requires a max_length attribute.
CharField๋ max_length ์์ด๋ ์์ ์คํ์ด ์ ๋ฉ๋๋ค.
max_length= "์ด ์นธ์๋ ์ต๋ ๋ช ๊ธ์๊น์ง ์ธ ์ ์๋์?" ๋ฅผ Django์ DB์๊ฒ ์๋ ค์ฃผ๋ ํ์ ์ค์
๊ถ๊ธํ ๊ฒ ์์ผ๋ฉด ๋ ๋ฌผ์ด๋ณด์ธ์! ๐
CharField default ์ต์ ์ด ๋ญ๊ฐ์?
default ์ต์
์ด๋?default๋ ์๋ฌด๊ฒ๋ ์
๋ ฅํ์ง ์์์ ๋ ์๋์ผ๋ก ์ฑ์์ง๋ ๊ธฐ๋ณธ๊ฐ์ ์ค์ ํ๋ ์ต์
์
๋๋ค.
ํ์๊ฐ์ ํผ์ ๋ ์ฌ๋ ค๋ณด์ธ์.
- ๊ตญ๊ฐ ์ ํ์นธ โ ์๋ฌด๊ฒ๋ ์ ๊ณ ๋ฅด๋ฉด ์๋์ผ๋ก "๋ํ๋ฏผ๊ตญ" ์ด ์ ํ๋จ
- ๋ฑ๊ธ ์นธ โ ์ฒ์ ๊ฐ์ ํ๋ฉด ์๋์ผ๋ก "์ผ๋ฐํ์" ์ผ๋ก ์ค์ ๋จ
์ด "์๋์ผ๋ก ์ฑ์์ง๋ ๊ฐ"์ด ๋ฐ๋ก
default์ ๋๋ค.
class User(models.Model):
username = models.CharField(max_length=50)
# default ์์ โ ๋ฐ๋์ ๊ฐ์ ๋ฃ์ด์ผ ํจ
country = models.CharField(max_length=50, default='๋ํ๋ฏผ๊ตญ')
# ์๋ฌด๊ฒ๋ ์ ์
๋ ฅํ๋ฉด ์๋์ผ๋ก '๋ํ๋ฏผ๊ตญ' ์ ์ฅ
grade = models.CharField(max_length=20, default='์ผ๋ฐํ์')
# ์๋ฌด๊ฒ๋ ์ ์
๋ ฅํ๋ฉด ์๋์ผ๋ก '์ผ๋ฐํ์' ์ ์ฅ
| ์ํฉ | default ์์ ๋ | default='์ผ๋ฐํ์' ์์ ๋ |
|---|---|---|
| ๊ฐ์ ์ ๋ ฅํจ | '๊ด๋ฆฌ์' ์ ์ฅ | '๊ด๋ฆฌ์' ์ ์ฅ |
| ๊ฐ์ ์ ์ ๋ ฅํจ | ์ค๋ฅ ๋ฐ์ | '์ผ๋ฐํ์' ์๋ ์ ์ฅ |
# 1. ๋น ๋ฌธ์์ด (๊ฐ์ฅ ๋ง์ด ์)
nickname = models.CharField(max_length=50, blank=True, default='')
# 2. ํน์ ๋ฌธ์์ด
grade = models.CharField(max_length=20, default='์ผ๋ฐํ์')
# 3. ํจ์๋ก ๋์ ์์ฑ (ํธ์ถ ๊ฐ๋ฅํ ๊ฐ์ฒด)
import uuid
code = models.CharField(max_length=36, default=uuid.uuid4)
# โ ์ ์ฅํ ๋๋ง๋ค ์๋์ผ๋ก ๊ณ ์ ํ ์ฝ๋ ์์ฑ
blank=True์ ํจ๊ป ์ฐ๋ ์ด์ blank=True โ ํผ์์ ๋น์๋ ๋จ
default='' โ ๋น์ ์ ๋ DB์ '' ๋ก ์ ์ฅ
์ด ๋ ๊ฐ๋ฅผ ํจ๊ป ์จ์ผ ์์ ํ "์ ํ ์
๋ ฅ ์นธ"์ด ์์ฑ๋จ
# CharField ์ ํ ์
๋ ฅ ์นธ์ ๊ถ์ฅ ํจํด
nickname = models.CharField(max_length=50, blank=True, default='')
# โ ํผ์์ ๋น์๋ ๋จ
# โ ๋น๋ฉด '' ๋ก ์ ์ฅ
default= "์๋ฌด๊ฒ๋ ์ ๋ ฅ ์ ํ๋ฉด ์ด ๊ฐ์ผ๋ก ์๋ ์ ์ฅํด์ค" ๋ผ๊ณ Django์๊ฒ ์๋ ค์ฃผ๋ ๊ฒ
from django.contrib import admin โ Django ๋ด์ฅ ๋ชจ๋django.contrib.admin์ Django๊ฐ ๊ธฐ๋ณธ ์ ๊ณตํ๋ ์๋ ๊ด๋ฆฌ์ ์ธํฐํ์ด์ค(Admin Site) ๋ชจ๋์
๋๋ค.
Django ํ๋ก์ ํธ๋ฅผ ๋ง๋ค๋ฉด /admin URL์์ ๋ฐ์ดํฐ๋ฒ ์ด์ค๋ฅผ GUI๋ก ๊ด๋ฆฌํ ์ ์๋ ํ์ด์ง๊ฐ ์๋ ์์ฑ๋ฉ๋๋ค. ์ด๊ฑธ ๊ฐ๋ฅํ๊ฒ ํด์ฃผ๋ ๊ฒ ๋ฐ๋ก django.contrib.admin์
๋๋ค.
1. ๋ชจ๋ธ ๋จ์ ๋ฑ๋ก
from django.contrib import admin
from .models import Article
admin.site.register(Article)
2. ModelAdmin์ผ๋ก ์ปค์คํฐ๋ง์ด์ง
from django.contrib import admin
from .models import Article
@admin.register(Article)
class ArticleAdmin(admin.ModelAdmin):
list_display = ['id', 'title', 'author', 'created_at'] # ๋ชฉ๋ก์ ํ์ํ ํ๋
list_filter = ['author', 'created_at'] # ์ค๋ฅธ์ชฝ ํํฐ ํจ๋
search_fields = ['title', 'content'] # ๊ฒ์์ฐฝ
ordering = ['-created_at'] # ์ ๋ ฌ ๊ธฐ์ค
readonly_fields = ['created_at'] # ์ฝ๊ธฐ ์ ์ฉ ํ๋
ModelAdmin ์ต์
์ ๋ฆฌ| ์ต์ | ์ค๋ช |
|---|---|
list_display | ๋ชฉ๋ก ํ์ด์ง์ ํ์ํ ์ปฌ๋ผ |
list_filter | ์ฌ์ด๋๋ฐ ํํฐ |
search_fields | ๊ฒ์ ๋์ ํ๋ |
ordering | ๊ธฐ๋ณธ ์ ๋ ฌ (-๋ ๋ด๋ฆผ์ฐจ์) |
readonly_fields | ์์ ๋ถ๊ฐ ํ๋ |
fields | ์์ธ ํ์ด์ง์ ํ์ํ ํ๋ ์์ |
inlines | ๊ด๋ จ ๋ชจ๋ธ์ ๊ฐ์ ํ์ด์ง์ ํ์ |
list_per_page | ํ์ด์ง๋น ํญ๋ชฉ ์ (๊ธฐ๋ณธ 100) |
settings.py์ INSTALLED_APPS์ ๋ฐ๋์ ํฌํจ๋์ด ์์ด์ผ ํฉ๋๋ค:
INSTALLED_APPS = [
'django.contrib.admin', # โ
์ด๋๋ฏผ
'django.contrib.auth', # ์ธ์ฆ
'django.contrib.contenttypes',
...
]
urls.py์๋ ๋ฑ๋ก:
from django.contrib import admin
from django.urls import path
urlpatterns = [
path('admin/', admin.site.urls), # /admin ์ ์ ๊ฒฝ๋ก
]
python manage.py createsuperuser
์ดํ /admin์ ์ ์ํ๋ฉด ๋ฑ๋ก๋ ๋ชจ๋ธ์ GUI๋ก CRUD ํ ์ ์์ต๋๋ค.
๊ถ๊ธํ ๋ถ๋ถ์ด ์์ผ๋ฉด ๋ ์ค๋ช ํด ๋๋ฆด๊ฒ์!
๋ฐ์ดํฐ๋ฅผ ๋ค๋ฃจ๋ 4๊ฐ์ง ๊ธฐ๋ณธ ๋์์ ์๊ธ์๋ฅผ ๋ด ์ฝ์์ ๋๋ค.
| ์ฝ์ | ์์ด | ํ๊ตญ์ด | ์์ |
|---|---|---|---|
| C | Create | ์์ฑ | ๊ฒ์๊ธ ์์ฑ |
| R | Read | ์กฐํ | ๊ฒ์๊ธ ๋ชฉ๋ก ๋ณด๊ธฐ |
| U | Update | ์์ | ๊ฒ์๊ธ ๋ด์ฉ ์์ |
| D | Delete | ์ญ์ | ๊ฒ์๊ธ ์ญ์ |
admin.py์ registerํ ๋ชจ๋ธ์ ๋งํฉ๋๋ค.
admin.site.register(Article) # Article ๋ชจ๋ธ์ ๋ฑ๋ก
โ ์ด๋ ๊ฒ ๋ฑ๋กํด์ผ /admin์์ ๋ณด์
๋๋ค.
"๋ธ๋ผ์ฐ์ ์์
/admin์ฃผ์๋ก ๋ค์ด๊ฐ๋ฉด,
๋ฑ๋กํด ๋์ DB ํ ์ด๋ธ(๋ชจ๋ธ)์
์ฝ๋ ํ ์ค ์์ด ํ๋ฉด ํด๋ฆญ๋ง์ผ๋ก
์ถ๊ฐ / ์กฐํ / ์์ / ์ญ์ ํ ์ ์๋ค"
โ ๋ธ๋ผ์ฐ์ ์์ localhost:8000/admin ์ ์
โ
โก ์ํผ์ ์ ๋ก ๋ก๊ทธ์ธ
โ
โข ๋ฑ๋ก๋ ๋ชจ๋ธ(์: Article) ํด๋ฆญ
โ
โฃ ๋ฒํผ ํด๋ฆญ์ผ๋ก CRUD ๊ฐ๋ฅ
- [์ถ๊ฐ] ๋ฒํผ โ Create (์์ฑ)
- ๋ชฉ๋ก ํ์ธ โ Read (์กฐํ)
- ํญ๋ชฉ ํด๋ฆญ โ Update (์์ )
- [์ญ์ ] ๋ฒํผ โ Delete (์ญ์ )
๊ฐ๋ฐ์๊ฐ ๋ณ๋์ ๊ด๋ฆฌ ํ์ด์ง๋ฅผ ๋ง๋ค์ง ์์๋, Django๊ฐ ์๋์ผ๋ก ๋ฐ์ดํฐ ๊ด๋ฆฌ ํ๋ฉด์ ๋ง๋ค์ด ์ค๋ค๋ ๋ป์ ๋๋ค! ๐
๊ทธ๋ํฝ ์ฌ์ฉ์ ์ธํฐํ์ด์ค โ ์ฆ, ๋ง์ฐ์ค๋ก ํด๋ฆญํ๊ณ ๋์ผ๋ก ๋ณด๋ฉด์ ์ฌ์ฉํ๋ ํ๋ฉด์ ๋๋ค.
| CLI | GUI | |
|---|---|---|
| ํ๋ค์ | Command Line Interface | Graphical User Interface |
| ์ฌ์ฉ ๋ฐฉ์ | ๋ช ๋ น์ด ํ์ดํ | ๋ง์ฐ์ค ํด๋ฆญ + ์๊ฐ์ ํ๋ฉด |
| ์์ | ํฐ๋ฏธ๋, ๋ช ๋ น ํ๋กฌํํธ | ์๋์ฐ ํ์๊ธฐ, ์นด์นด์คํก, ์น์ฌ์ดํธ |
CLI ๋ฐฉ์ (๋ช ๋ น์ด๋ก ๋ฐ์ดํฐ ์กฐํ):
SELECT * FROM article WHERE id = 1;
GUI ๋ฐฉ์ (Django Admin):
โ ๋ธ๋ผ์ฐ์ ์์ /admin ์ ์ํ๋ฉด ์๋์ฒ๋ผ ๋ฒํผ, ํ, ์
๋ ฅ์ฐฝ์ผ๋ก ๋๊ฐ์ ์์
์ ํ ์ ์์
โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
โ Articles [+์ถ๊ฐ]โ
โโโโโโฌโโโโโโโโโโโฌโโโโโโโโโโโโโโโโโค
โ ID โ ์ ๋ชฉ โ ์์ฑ์ โ
โโโโโโผโโโโโโโโโโโผโโโโโโโโโโโโโโโโโค
โ 1 โ ์๋
ํ์ธ์โ admin โ
โ 2 โ ํ
์คํธ โ user1 โ
โโโโโโดโโโโโโโโโโโดโโโโโโโโโโโโโโโโโ
CLI = ์ฝ๋/๋ช ๋ น์ด๋ก ์กฐ์
GUI = ๋์ ๋ณด์ด๋ ํ๋ฉด์ผ๋ก ์กฐ์
Django Admin์ด GUI๋ผ๋ ๊ฑด, ์ฝ๋ ์์ด ๋ธ๋ผ์ฐ์ ์์ ํด๋ฆญ๋ง์ผ๋ก DB๋ฅผ ๊ด๋ฆฌํ ์ ์๋ค๋ ๋ป์ ๋๋ค! ๐
from django.contrib import admin ์ค๋ช
"Django๊ฐ ๋ง๋ค์ด๋์ ๊ด๋ฆฌ์ ํ์ด์ง ๊ธฐ๋ฅ์ ๊ฐ์ ธ์ค๋ ๊ฒ" ์ด์์!
from django.contrib import admin
โ โ โ โ
from django contrib admin
๊ฐ์ ธ์ ์ฅ๊ณ ์์ ๋ด์ฅ์ฑ ๊ด๋ฆฌ์๊ธฐ๋ฅ
django
โโโ contrib โ "contributed(๊ธฐ์ฌํ๋ค) apps" ์ ์ฝ์
โโโ admin โ ๊ด๋ฆฌ์ ํ์ด์ง
โโโ auth โ ๋ก๊ทธ์ธ/์ธ์ฆ
โโโ sessions โ ์ธ์
๊ด๋ฆฌ
โโโ messages โ ๋ฉ์์ง ์๋ฆผ
โโโ staticfiles โ ์ ์ ํ์ผ
Django ๊ฐ ๊ธฐ๋ณธ์ผ๋ก
์ ๊ณตํ๋ ๋ด์ฅ ์ฑ ๋ชจ์! ๐ฆ
โ ์ค์น ์์ด ๋ฐ๋ก ์ฌ์ฉ ๊ฐ๋ฅ!
from django.contrib import admin
# 1. ๋ชจ๋ธ ๋ฑ๋ก
admin.site.register(Study)
# 2. ์ปค์คํ
Admin ํด๋์ค
class StudyAdmin(admin.ModelAdmin):
list_display = ['title', 'category']
# 3. ๋ฐ์ฝ๋ ์ดํฐ ๋ฐฉ์
@admin.register(Study)
class StudyAdmin(admin.ModelAdmin):
list_display = ['title']
๊ธฐ๋ณธ ๋ฑ๋ก - ์๋ฌด ์ค์ ์์ด ๊ทธ๋ฅ ๋ฑ๋ก
admin.site.register(Study)
โ /admin์์ Study ๋ชฉ๋ก์ด ๊ธฐ๋ณธ ํํ๋ก๋ง ๋ณด์
์ปค์คํ Admin ํด๋์ค - ์ด๋ป๊ฒ ๋ณด์ฌ์ค์ง ์ง์ ์ค์
class StudyAdmin(admin.ModelAdmin):
list_display = ['title', 'category']
admin.site.register(Study, StudyAdmin) # โ ๋์ ์ฐ๊ฒฐ
โ /admin์์ Study ๋ชฉ๋ก์ ์ํ๋ ํํ๋ก ๋ณด์ฌ์ค
list_display = ['title', 'category'] ์๋ฏธ/admin์ ๋ชฉ๋ก ํ์ด์ง์ ์ด๋ค ์ปฌ๋ผ์ ํ์ํ ์ง ์ง์ ํ๋ ์ต์
์
๋๋ค.
์ค์ ์
โโโโโโโโโโโโโโโโโโโโโโโ
โ Study object (1) โ โ ์ด๋ ๊ฒ๋ง ๋ณด์
โ Study object (2) โ
โโโโโโโโโโโโโโโโโโโโโโโ
์ค์ ํ
โโโโโโโโโโโโโโโโฌโโโโโโโโโโโโโโโ
โ title โ category โ โ ์ปฌ๋ผ์ด ๋ณด์
โโโโโโโโโโโโโโโโผโโโโโโโโโโโโโโโค
โ Django ๊ณต๋ถ โ ๋ฐฑ์๋ โ
โ React ๊ณต๋ถ โ ํ๋ก ํธ์๋ โ
โโโโโโโโโโโโโโโโดโโโโโโโโโโโโโโโ
admin.ModelAdmin์ ์์๋ฐ์์,
/adminํ์ด์ง๋ฅผ ๋ด๊ฐ ์ํ๋ ๋๋ก ์ปค์คํฐ๋ง์ด์งํ๋ ํด๋์ค์ ๋๋ค! โ
@admin.register(Study) ์๋ฏธํจ์/ํด๋์ค ์์ @๋ฅผ ๋ถ์ฌ์, ์ถ๊ฐ ๋์์ ์๋์ผ๋ก ์คํ์ํค๋ ๋ฌธ๋ฒ์
๋๋ค.
๊ธฐ์กด ๋ฐฉ์ (2๋จ๊ณ)
# โ ํด๋์ค ์ ์
class StudyAdmin(admin.ModelAdmin):
list_display = ['title', 'category']
# โก ๋ฐ๋ก ๋ฑ๋ก
admin.site.register(Study, StudyAdmin)
๋ฐ์ฝ๋ ์ดํฐ ๋ฐฉ์ (1๋จ๊ณ)
# โ ์ ์ + ๋ฑ๋ก์ ๋์์!
@admin.register(Study)
class StudyAdmin(admin.ModelAdmin):
list_display = ['title', 'category']
@admin.register(Study) ํ์ด@admin.register(Study) # โ "Study ๋ชจ๋ธ์ ์๋ ํด๋์ค๋ฅผ ์ฐ๊ฒฐํด์ ๋ฑ๋กํด์ค"
class StudyAdmin(admin.ModelAdmin):
list_display = ['title', 'category']
| ๋ถ๋ถ | ์๋ฏธ |
|---|---|
@ | ๋ฐ์ฝ๋ ์ดํฐ ํ์ |
admin.register | ๋ฑ๋ก ๋์์ ์ํํ๋ ํจ์ |
(Study) | ์ด๋ค ๋ชจ๋ธ์ ์ฐ๊ฒฐํ ์ง ์ง์ |
StudyAdmin | ์ด๋๋ฏผ ์ค์ ํด๋์ค |
@admin.register(Study)=
admin.site.register(Study, StudyAdmin)์
์๋์ผ๋ก ์คํํด์ฃผ๋ ์ถ์ฝ ๋ฌธ๋ฒ
์ฝ๋๊ฐ ์งง์์ง๊ณ , ๋ชจ๋ธ๊ณผ ์ค์ ํด๋์ค๊ฐ ํ๋์ ๋ณด์ฌ์ ๊ฐ๋ ์ฑ์ด ์ข์์ง๋๋ค! โ
http://localhost:8000/admin
โโโโโโโโโโโโโโโโโโโโโโโโโโโ
โ Django ๊ด๋ฆฌ์ ํ์ด์ง โ
โโโโโโโโโโโโโโโโโโโโโโโโโโโค
โ ๐ Study โ
โ + ์ถ๊ฐ โ
โ ๐ ๋ชฉ๋ก๋ณด๊ธฐ โ
โโโโโโโโโโโโโโโโโโโโโโโโโโโค
โ ๐ค Users โ
โ ๐ Groups โ
โโโโโโโโโโโโโโโโโโโโโโโโโโโ
# settings.py
INSTALLED_APPS = [
'django.contrib.admin', # โ ์ฌ๊ธฐ ๋ฑ๋ก๋์ด ์์ด์ผ
'django.contrib.auth',
'django.contrib.sessions',
...
]
# ๊ทธ๋์ผ admin.py ์์
from django.contrib import admin # ์ฌ์ฉ ๊ฐ๋ฅ! โ
# ๊ด๋ฆฌ์ ํ์ด์ง
from django.contrib import admin
# ๋ก๊ทธ์ธ/์ธ์ฆ
from django.contrib.auth.models import User
# ๋ฉ์์ง ์๋ฆผ
from django.contrib import messages
# ๋ก๊ทธ์ธ ํ์ ๋ฐ์ฝ๋ ์ดํฐ
from django.contrib.auth.decorators import login_required
django.contrib
= ์ค๋งํธํฐ ๊ธฐ๋ณธ ์ฑ ๐ฑ
์ค์น ์์ด ์ฒ์๋ถํฐ
์ ๊ณต๋๋ ์ฑ๋ค!
admin = ๊ธฐ๋ณธ ํ์ผ๊ด๋ฆฌ์ฑ
auth = ๊ธฐ๋ณธ ์ ๊ธํ๋ฉด
sessions = ๊ธฐ๋ณธ ๋ฉ๋ชจ๋ฆฌ
messages = ๊ธฐ๋ณธ ์๋ฆผ
| ์ฝ๋ | ์๋ฏธ |
|---|---|
from | ๊ฐ์ ธ์ |
django | Django ํจํค์ง์์ |
contrib | ๋ด์ฅ ์ฑ ๋ชจ์์์ |
admin | ๊ด๋ฆฌ์ ๊ธฐ๋ฅ์ |
import | ๋ถ๋ฌ์ด |
๐ก
admin.pyํ์ผ์์
์ด ํ ์ค ์์ผ๋ฉด ์๋ฌด๊ฒ๋ ๋ชปํด์!
Django ์ฑ ๋ง๋ค๋ฉด ์๋์ผ๋ก ์์ฑ๋๋ํ์ import ์์! โ
from django.db import models โ Django ๋ด์ฅ ๋ชจ๋์ด๊ฑด Django๊ฐ ๊ธฐ๋ณธ์ผ๋ก ์ ๊ณตํ๋ ๋ด์ฅ ๋ชจ๋์ ๋๋ค.
Django์์ ๋ฐ์ดํฐ๋ฒ ์ด์ค ๋ชจ๋ธ์ ์ ์ํ ๋ ์ฌ์ฉํ๋ ํต์ฌ ๋ชจ๋์ด์์.
from django.db import models
class Study(models.Model):
title = models.CharField(max_length=100)
created_at = models.DateTimeField(auto_now_add=True)
models ์์ ๋ค์ด์๋ ์ฃผ์ ๋ด์ฅ ๊ธฐ๋ฅ๋คmodels.CharField() # ์งง์ ๋ฌธ์์ด
models.TextField() # ๊ธด ๋ฌธ์์ด
models.IntegerField() # ์ ์
models.FloatField() # ์ค์
models.BooleanField() # True/False
models.DateField() # ๋ ์ง
models.DateTimeField() # ๋ ์ง+์๊ฐ
models.EmailField() # ์ด๋ฉ์ผ
models.ImageField() # ์ด๋ฏธ์ง ํ์ผ
models.FileField() # ํ์ผ
models.ForeignKey() # 1:N ๊ด๊ณ
models.ManyToManyField() # N:N ๊ด๊ณ
models.OneToOneField() # 1:1 ๊ด๊ณ
class Study(models.Model): # ์ด๊ฑธ ์์๋ฐ์์ผ DB ํ
์ด๋ธ์ด ๋จ
...
class Study(models.Model):
class Meta:
ordering = ['-created_at'] # ๊ธฐ๋ณธ ์ ๋ ฌ
db_table = 'my_study' # ํ
์ด๋ธ ์ด๋ฆ ์ง์
verbose_name = '์คํฐ๋' # ๊ด๋ฆฌ์ ํ์ด์ง ํ์๋ช
# DB ๋ชจ๋ธ
from django.db import models
# ๋ทฐ
from django.shortcuts import render, redirect, get_object_or_404
# URL
from django.urls import path, include
# ์ธ์ฆ
from django.contrib.auth.models import User
from django.contrib.auth.decorators import login_required
# ํผ
from django.forms import ModelForm
# ์ค์
from django.conf import settings
ํต์ฌ ์์ฝ: from django.db import models๋ Django๊ฐ ์ค์น๋ ๋ ํจ๊ป ์ ๊ณต๋๋ ๋ด์ฅ ๋ชจ๋์ด๊ณ , ์ด๊ฑธ ํตํด Python ํด๋์ค๋ฅผ DB ํ
์ด๋ธ๋ก ๋ณํํ ์ ์์ด์! ๐ฏ