๐Ÿ”ฅDjango ๊ธฐ์ดˆ - ๊ณต๋ถ€์‹œ๊ฐ„ ๊ธฐ๋ก๊ธฐ ๋งŒ๋“ค๊ธฐ(1)

HY_1023ยท2026๋…„ 4์›” 7์ผ

MENTOS

๋ชฉ๋ก ๋ณด๊ธฐ
18/19

https://www.figma.com/design/wDh3su4KrlhkzOM1d7vKBT/Django-%EA%B8%B0%EC%B4%88---%EA%B3%B5%EB%B6%80%EC%8B%9C%EA%B0%84-%EA%B8%B0%EB%A1%9D%EA%B8%B0-%EB%A7%8C%EB%93%A4%EA%B8%B0-2-?node-id=0-1&t=v5jE7SjThGqnU9an-1

๊ฐ€์ƒํ™˜๊ฒฝ ์„ค์ •๋ถ€ํ„ฐ ํ”„๋กœ์ ํŠธ ์ƒ์„ฑ, ์•ฑ ๋“ฑ๋ก, ๋ชจ๋ธ ์ž‘์„ฑ, ๋งˆ์ด๊ทธ๋ ˆ์ด์…˜, admin ํ™•์ธ, URL ์—ฐ๊ฒฐ, ํ…œํ”Œ๋ฆฟ๊ณผ CSS ์ ์šฉ, ํ•จ์ˆ˜ํ˜• View๋ฅผ ์ด์šฉํ•œ ๋ชฉ๋ก ํŽ˜์ด์ง€ ๊ตฌํ˜„๊นŒ์ง€ ์•„์ฃผ ์ž์„ธํžˆ ์‹ค์Šตํ•ฉ๋‹ˆ๋‹ค.

ํŒŒ์ผ์—ญํ• 
manage.pyDjango ๋ช…๋ น ์‹คํ–‰ ์ง„์ž…์ 
config/settings.pyํ”„๋กœ์ ํŠธ ์ „์ฒด ์„ค์ • ํŒŒ์ผ
config/urls.py์ตœ์ƒ์œ„ URL ์—ฐ๊ฒฐ ํŒŒ์ผ
config/wsgi.py๋ฐฐํฌ์šฉ ์„œ๋ฒ„ ์—ฐ๊ฒฐ
config/asgi.py๋น„๋™๊ธฐ ์„œ๋ฒ„ ์—ฐ๊ฒฐ

manage ๊ด€๋ฆฌํ•˜๋‹ค
config ๊ตฌ์„ฑ
setting ํ™˜๊ฒฝ


ํ”„๋กœ์ ํŠธ์ƒ์„ฑ๊ณผ ์•ฑ์ƒ์„ฑ์˜ ์ฐจ์ด

7. Django ํ”„๋กœ์ ํŠธ ์ƒ์„ฑ

์ด์ œ 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


9. ์•ฑ ์ƒ์„ฑ

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 ๋ถ„์•ผ


11๋ฒˆ๊นŒ์ง€๋Š” ์ตœ์†Œํ•œ์˜ ์„ธํŒ…

12๋ฒˆ๋ถ€ํ„ฐ ์ค‘์š”!

--> ๊ธฐ๋ณธ์ ์ธ ๊ธฐ์ดˆ์ ์ธ ๊ฐœ๋…์ด ํ•„์š”.



CATEGORY ๋ฒ”์ฃผ
algorithm ์—ฐ์‚ฐ
verbose ๋ง ์ˆ˜๊ฐ€ ๋งŽ์€
PositiveInteger ์–‘์˜ ์ •์ˆ˜
ordering ์ฃผ๋ฌธ
verbose_name
plural ๋ณต์ˆ˜์˜
return ๋ฐ˜ํ™˜ํ•˜๋‹ค
property ์žฌ์‚ฐ ์†Œ์œ ํ•˜๋‹ค
import ์ˆ˜์ž…
blank ๊ณต๋ฐฑ


1๏ธโƒฃ "๋ฌด์—‡์„ ๋‹ด์„๊นŒ" ์ƒ๊ฐํ•˜๋Š” ๋ฒ•

๋ชจ๋ธ์„ ์„ค๊ณ„ํ•  ๋•Œ๋Š” ์ฝ”๋“œ๋ณด๋‹ค "์ด ์„œ๋น„์Šค๊ฐ€ ๊ธฐ์–ตํ•ด์•ผ ํ•  ์ •๋ณด๊ฐ€ ๋ญ”๊ฐ€?" ๋ฅผ ๋จผ์ € ์ƒ๊ฐํ•ฉ๋‹ˆ๋‹ค.

๊ณต๋ถ€ ๊ธฐ๋ก ์•ฑ์ด ๊ธฐ์–ตํ•ด์•ผ ํ•  ๊ฒƒ๋“ค์„ ๋ฉ”๋ชจ์ง€์— ์ ๋“ฏ์ด ๋‚˜์—ด

โ†’ ๋ฌด์Šจ ๊ณต๋ถ€๋ฅผ ํ–ˆ๋‚˜?        (title)
โ†’ ์–ด๋–ค ์นดํ…Œ๊ณ ๋ฆฌ์ธ๊ฐ€?       (category)
โ†’ ์–ธ์ œ ๊ณต๋ถ€ํ–ˆ๋‚˜?           (study_date)
โ†’ ๋ช‡ ์‹œ๊ฐ„ ํ–ˆ๋‚˜?            (hours / minutes)
โ†’ ๋ฉ”๋ชจํ•  ๊ฒŒ ์žˆ๋‚˜?          (memo)
โ†’ ์–ธ์ œ ์ด ๊ธฐ๋ก์„ ๋งŒ๋“ค์—ˆ๋‚˜? (created_at)
โ†’ ๋งˆ์ง€๋ง‰์œผ๋กœ ์ˆ˜์ •ํ•œ ๊ฑด?    (updated_at)

์ด๋ ‡๊ฒŒ ์ž์—ฐ์–ด๋กœ ๋จผ์ € ๋‚˜์—ดํ•œ ๋‹ค์Œ, ๊ฐ ํ•ญ๋ชฉ์— ๋งž๋Š” ํ•„๋“œ ํƒ€์ž…์„ ๊ณจ๋ผ ์ฝ”๋“œ๋กœ ์˜ฎ๊ธฐ๋Š” ์ˆœ์„œ์ž…๋‹ˆ๋‹ค.


2๏ธโƒฃ models.py ํฐ ๊ตฌ์กฐ---

3๏ธโƒฃ ์ฝ”๋“œ ํ•œ ์ค„์”ฉ ํ•ด์„

โ‘  ์„ ํƒ์ง€ ์ƒ์ˆ˜ CATEGORY_CHOICES

CATEGORY_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

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๋ถ„)

4๏ธโƒฃ ๋ชจ๋ธ ์„ค๊ณ„ ์ˆœ์„œ ์š”์•ฝ

1๋‹จ๊ณ„  ๊ธฐ์–ตํ•ด์•ผ ํ•  ์ •๋ณด๋ฅผ ์ž์—ฐ์–ด๋กœ ๋‚˜์—ด
          "์ œ๋ชฉ, ๋‚ ์งœ, ์‹œ๊ฐ„, ๋ฉ”๋ชจ..."

2๋‹จ๊ณ„  ๊ฐ ์ •๋ณด์— ๋งž๋Š” ํ•„๋“œ ํƒ€์ž… ์„ ํƒ
          ๊ธ€์ž โ†’ CharField / TextField
          ์ˆซ์ž โ†’ IntegerField
          ๋‚ ์งœ โ†’ DateField

3๋‹จ๊ณ„  ๊ฐ ํ•„๋“œ์— ์˜ต์…˜ ์ถ”๊ฐ€
          ํ•„์ˆ˜์ธ์ง€? ๊ธฐ๋ณธ๊ฐ’์€? ์ตœ๋Œ€ ๊ธธ์ด๋Š”?

4๋‹จ๊ณ„  Meta, __str__, property ์ถ”๊ฐ€
          ์ •๋ ฌ ๋ฐฉ์‹, ํ‘œ์‹œ ์ด๋ฆ„, ๊ณ„์‚ฐ ์†์„ฑ

์ด ์ˆœ์„œ๋กœ ์ƒ๊ฐํ•˜๋ฉด ์–ด๋–ค ๋ชจ๋ธ์ด๋“  ๋ง‰ํžˆ์ง€ ์•Š๊ณ  ์ž‘์„ฑํ•  ์ˆ˜ ์žˆ์–ด์š”! ๋” ๊ถ๊ธˆํ•œ ๋ถ€๋ถ„ ์žˆ์œผ๋ฉด ์•Œ๋ ค์ฃผ์„ธ์š” ๐Ÿ˜Š


CharField๋Š” Django ๋ชจ๋ธ์—์„œ ๊ฐ€์žฅ ์ž์ฃผ ์“ฐ๋Š” ํ•„๋“œ ์ค‘ ํ•˜๋‚˜๋กœ, ์งง์€ ํ…์ŠคํŠธ๋ฅผ ์ €์žฅํ•˜๋Š” ์นธ์ž…๋‹ˆ๋‹ค. ์ด๋ฆ„, ์ œ๋ชฉ, ์ฃผ์†Œ์ฒ˜๋Ÿผ ํ•œ ์ค„์งœ๋ฆฌ ๊ธ€์ž๋ฅผ ๋‹ด์„ ๋•Œ ์”๋‹ˆ๋‹ค.

์•„๋ž˜ ํ๋ฆ„๋„๋กœ ์ „์ฒด ๊ฐœ๋…์„ ํ•œ๋ˆˆ์— ํ™•์ธํ•ด ๋ณด์„ธ์š”.---

ํ•ต์‹ฌ ๊ฐœ๋… ์ •๋ฆฌ

CharField = "์งง์€ ๊ธ€์ž๋ฅผ ์ €์žฅํ•˜๋Š” ์นธ"

์—‘์…€์˜ ์…€ ํ•˜๋‚˜๋ผ๊ณ  ์ƒ๊ฐํ•˜๋ฉด ์‰ฌ์›Œ์š”. ์ด๋ฆ„, ์ œ๋ชฉ, ๋ธŒ๋žœ๋“œ๋ช…์ฒ˜๋Ÿผ ํ•œ ์ค„์งœ๋ฆฌ ํ…์ŠคํŠธ๋ฅผ ๋‹ด๋Š” ์šฉ๋„์ž…๋‹ˆ๋‹ค.

name = models.CharField(max_length=100)

์ด ํ•œ ์ค„์ด DB์— VARCHAR(100) ์ปฌ๋Ÿผ ํ•˜๋‚˜๋ฅผ ๋งŒ๋“ค์–ด ์ค๋‹ˆ๋‹ค.


์˜ต์…˜ ์„ค๋ช…

์˜ต์…˜์—ญํ• ์˜ˆ์‹œ
max_length์ตœ๋Œ€ ๊ธ€์ž ์ˆ˜ (ํ•„์ˆ˜!)max_length=100
blank=Trueํผ์—์„œ ๋น„์›Œ๋„ ๋จ์„ ํƒ ์ž…๋ ฅ ํ•ญ๋ชฉ์— ์‚ฌ์šฉ
null=TrueDB์— NULL ์ €์žฅ ํ—ˆ์šฉblank์™€ ํ•จ๊ป˜ ์“ธ ๋•Œ๊ฐ€ ๋งŽ์Œ
default=''๊ธฐ๋ณธ๊ฐ’ ์„ค์ •์•„๋ฌด๊ฒƒ๋„ ์•ˆ ์ž…๋ ฅํ•˜๋ฉด ์ด ๊ฐ’

blank์™€ null์˜ ์ฐจ์ด๊ฐ€ ํ—ท๊ฐˆ๋ฆด ์ˆ˜ ์žˆ๋Š”๋ฐ, blank๋Š” "ํผ ์ž…๋ ฅ ๊ฒ€์ฆ", null์€ "DB ์ €์žฅ" ์˜ ๋ฌธ์ œ์ž…๋‹ˆ๋‹ค.


CharField๋ฅผ ์จ์•ผ ํ•  ๋•Œ vs ๋ง์•„์•ผ ํ•  ๋•Œ

  • ์จ์•ผ ํ•  ๋•Œ: ์ด๋ฆ„, ์ œ๋ชฉ, ์ฃผ์†Œ, ์ „ํ™”๋ฒˆํ˜ธ์ฒ˜๋Ÿผ ์งง์€ ํ•œ ์ค„ ํ…์ŠคํŠธ
  • 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=TrueDB์— ์ €์žฅํ•  ๋•Œ"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 ์ €์žฅ

DB์— ์‹ค์ œ๋กœ ์–ด๋–ป๊ฒŒ ์ €์žฅ๋˜๋‚˜?

์ƒํ™ฉ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์—์„œ ๊ถŒ์žฅํ•˜๋Š” ํŒจํ„ด

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๊ฐ€ ํ•˜๋Š” ์ผ 2๊ฐ€์ง€

max_length=50 ์„ค์ • ์‹œ

โ‘  DB ํ…Œ์ด๋ธ” ์ƒ์„ฑํ•  ๋•Œ
   โ†’ VARCHAR(50) ์ปฌ๋Ÿผ์œผ๋กœ ๋งŒ๋“ค์–ด์ง
   โ†’ DB ์ž์ฒด์—์„œ 50์ž ์ดˆ๊ณผ ์ €์žฅ ์ฐจ๋‹จ

โ‘ก ํผ(ํ™”๋ฉด) ์ž…๋ ฅํ•  ๋•Œ
   โ†’ 51์ž ์ด์ƒ ์ž…๋ ฅํ•˜๋ฉด "์ด ํ•„๋“œ์˜ ์ตœ๋Œ€ ๊ธธ์ด๋Š” 50์ž…๋‹ˆ๋‹ค" ์˜ค๋ฅ˜ ๋ฐœ์ƒ
   โ†’ Django๊ฐ€ ์ž๋™์œผ๋กœ ๊ฒ€์ฆํ•ด์คŒ

์ ์ ˆํ•œ max_length ๊ฐ’ ๊ฐ€์ด๋“œ

์ €์žฅํ•  ๋‚ด์šฉ๊ถŒ์žฅ ๊ฐ’์ด์œ 
์ด๋ฆ„, ๋‹‰๋„ค์ž„50๋Œ€๋ถ€๋ถ„ 50์ž ์ด๋‚ด
์ด๋ฉ”์ผ ์ฃผ์†Œ200์ด๋ฉ”์ผ ์ตœ๋Œ€ ๊ธธ์ด ๊ทœ๊ฒฉ
์ œ๋ชฉ, ์ƒํ’ˆ๋ช…100~200์—ฌ์œ  ์žˆ๊ฒŒ ์„ค์ •
์ฃผ์†Œ255๊ธด ์ฃผ์†Œ ๋Œ€๋น„
๋น„๋ฐ€๋ฒˆํ˜ธ(ํ•ด์‹œ)128์•”ํ˜ธํ™”๋œ ๋ฌธ์ž์—ด ๊ธธ์ด

๊ธด ๊ธ€(๊ฒŒ์‹œ๊ธ€ ๋ณธ๋ฌธ, ๋ฆฌ๋ทฐ ๋‚ด์šฉ ๋“ฑ)์€ max_length๊ฐ€ ์—†๋Š” TextField๋ฅผ ์“ฐ๋Š” ๊ฒŒ ๋งž์Šต๋‹ˆ๋‹ค.


max_length๋ฅผ ๋น ๋œจ๋ฆฌ๋ฉด?

# ์ด๋ ‡๊ฒŒ ์“ฐ๋ฉด ์˜ค๋ฅ˜ ๋ฐœ์ƒ!
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='์ผ๋ฐ˜ํšŒ์›')
    # ์•„๋ฌด๊ฒƒ๋„ ์•ˆ ์ž…๋ ฅํ•˜๋ฉด ์ž๋™์œผ๋กœ '์ผ๋ฐ˜ํšŒ์›' ์ €์žฅ

DB์— ์‹ค์ œ๋กœ ์–ด๋–ป๊ฒŒ ์ €์žฅ๋˜๋‚˜?

์ƒํ™ฉ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 ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

๊ถ๊ธˆํ•œ ๋ถ€๋ถ„์ด ์žˆ์œผ๋ฉด ๋” ์„ค๋ช…ํ•ด ๋“œ๋ฆด๊ฒŒ์š”!


"๋“ฑ๋ก๋œ ๋ชจ๋ธ์„ GUI๋กœ CRUD ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค" ์˜๋ฏธ


๋จผ์ € CRUD๋ž€?

๋ฐ์ดํ„ฐ๋ฅผ ๋‹ค๋ฃจ๋Š” 4๊ฐ€์ง€ ๊ธฐ๋ณธ ๋™์ž‘์˜ ์•ž๊ธ€์ž๋ฅผ ๋”ด ์•ฝ์ž์ž…๋‹ˆ๋‹ค.

์•ฝ์ž์˜์–ดํ•œ๊ตญ์–ด์˜ˆ์‹œ
CCreate์ƒ์„ฑ๊ฒŒ์‹œ๊ธ€ ์ž‘์„ฑ
RRead์กฐํšŒ๊ฒŒ์‹œ๊ธ€ ๋ชฉ๋ก ๋ณด๊ธฐ
UUpdate์ˆ˜์ •๊ฒŒ์‹œ๊ธ€ ๋‚ด์šฉ ์ˆ˜์ •
DDelete์‚ญ์ œ๊ฒŒ์‹œ๊ธ€ ์‚ญ์ œ

"๋“ฑ๋ก๋œ ๋ชจ๋ธ" ์ด๋ž€?

admin.py์— registerํ•œ ๋ชจ๋ธ์„ ๋งํ•ฉ๋‹ˆ๋‹ค.

admin.site.register(Article)  # Article ๋ชจ๋ธ์„ ๋“ฑ๋ก

โ†’ ์ด๋ ‡๊ฒŒ ๋“ฑ๋กํ•ด์•ผ /admin์—์„œ ๋ณด์ž…๋‹ˆ๋‹ค.


์ „์ฒด ๋ฌธ์žฅ ํ’€์ด

"๋ธŒ๋ผ์šฐ์ €์—์„œ /admin ์ฃผ์†Œ๋กœ ๋“ค์–ด๊ฐ€๋ฉด,
๋“ฑ๋กํ•ด ๋†“์€ DB ํ…Œ์ด๋ธ”(๋ชจ๋ธ)์„
์ฝ”๋“œ ํ•œ ์ค„ ์—†์ด ํ™”๋ฉด ํด๋ฆญ๋งŒ์œผ๋กœ
์ถ”๊ฐ€ / ์กฐํšŒ / ์ˆ˜์ • / ์‚ญ์ œ ํ•  ์ˆ˜ ์žˆ๋‹ค"


์‹ค์ œ ํ๋ฆ„

โ‘  ๋ธŒ๋ผ์šฐ์ €์—์„œ localhost:8000/admin ์ ‘์†
        โ†“
โ‘ก ์Šˆํผ์œ ์ €๋กœ ๋กœ๊ทธ์ธ
        โ†“
โ‘ข ๋“ฑ๋ก๋œ ๋ชจ๋ธ(์˜ˆ: Article) ํด๋ฆญ
        โ†“
โ‘ฃ ๋ฒ„ํŠผ ํด๋ฆญ์œผ๋กœ CRUD ๊ฐ€๋Šฅ
   - [์ถ”๊ฐ€] ๋ฒ„ํŠผ โ†’ Create (์ƒ์„ฑ)
   - ๋ชฉ๋ก ํ™•์ธ   โ†’ Read   (์กฐํšŒ)
   - ํ•ญ๋ชฉ ํด๋ฆญ   โ†’ Update (์ˆ˜์ •)
   - [์‚ญ์ œ] ๋ฒ„ํŠผ โ†’ Delete (์‚ญ์ œ)

ํ•ต์‹ฌ ์š”์•ฝ

๊ฐœ๋ฐœ์ž๊ฐ€ ๋ณ„๋„์˜ ๊ด€๋ฆฌ ํŽ˜์ด์ง€๋ฅผ ๋งŒ๋“ค์ง€ ์•Š์•„๋„, Django๊ฐ€ ์ž๋™์œผ๋กœ ๋ฐ์ดํ„ฐ ๊ด€๋ฆฌ ํ™”๋ฉด์„ ๋งŒ๋“ค์–ด ์ค€๋‹ค๋Š” ๋œป์ž…๋‹ˆ๋‹ค! ๐ŸŽ‰


GUI (Graphical User Interface)

๊ทธ๋ž˜ํ”ฝ ์‚ฌ์šฉ์ž ์ธํ„ฐํŽ˜์ด์Šค โ€” ์ฆ‰, ๋งˆ์šฐ์Šค๋กœ ํด๋ฆญํ•˜๊ณ  ๋ˆˆ์œผ๋กœ ๋ณด๋ฉด์„œ ์‚ฌ์šฉํ•˜๋Š” ํ™”๋ฉด์ž…๋‹ˆ๋‹ค.


CLI vs GUI ๋น„๊ต

CLIGUI
ํ’€๋„ค์ž„Command Line InterfaceGraphical 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 ๋ž€?

django
  โ””โ”€โ”€ contrib  โ† "contributed(๊ธฐ์—ฌํ•˜๋‹ค) apps" ์˜ ์•ฝ์ž
        โ”œโ”€โ”€ admin      โ†’ ๊ด€๋ฆฌ์ž ํŽ˜์ด์ง€
        โ”œโ”€โ”€ auth       โ†’ ๋กœ๊ทธ์ธ/์ธ์ฆ
        โ”œโ”€โ”€ sessions   โ†’ ์„ธ์…˜ ๊ด€๋ฆฌ
        โ”œโ”€โ”€ messages   โ†’ ๋ฉ”์‹œ์ง€ ์•Œ๋ฆผ
        โ””โ”€โ”€ staticfiles โ†’ ์ •์  ํŒŒ์ผ

ํ•œ ๋งˆ๋””๋กœ

Django ๊ฐ€ ๊ธฐ๋ณธ์œผ๋กœ
์ œ๊ณตํ•˜๋Š” ๋‚ด์žฅ ์•ฑ ๋ชจ์Œ! ๐Ÿ“ฆ
โ†’ ์„ค์น˜ ์—†์ด ๋ฐ”๋กœ ์‚ฌ์šฉ ๊ฐ€๋Šฅ!

admin ์ด ์ œ๊ณตํ•˜๋Š” ๊ฒƒ

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 ํด๋ž˜์Šค ์˜๋ฏธ

๊ธฐ๋ณธ ๋“ฑ๋ก vs ์ปค์Šคํ…€ ๋“ฑ๋ก ๋น„๊ต

๊ธฐ๋ณธ ๋“ฑ๋ก - ์•„๋ฌด ์„ค์ • ์—†์ด ๊ทธ๋ƒฅ ๋“ฑ๋ก

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) ์˜๋ฏธ


๋ฐ์ฝ”๋ ˆ์ดํ„ฐ๋ž€?

ํ•จ์ˆ˜/ํด๋ž˜์Šค ์œ„์— @๋ฅผ ๋ถ™์—ฌ์„œ, ์ถ”๊ฐ€ ๋™์ž‘์„ ์ž๋™์œผ๋กœ ์‹คํ–‰์‹œํ‚ค๋Š” ๋ฌธ๋ฒ•์ž…๋‹ˆ๋‹ค.


๊ธฐ์กด ๋ฐฉ์‹ vs ๋ฐ์ฝ”๋ ˆ์ดํ„ฐ ๋ฐฉ์‹ ๋น„๊ต

๊ธฐ์กด ๋ฐฉ์‹ (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)์„
์ž๋™์œผ๋กœ ์‹คํ–‰ํ•ด์ฃผ๋Š” ์ถ•์•ฝ ๋ฌธ๋ฒ•

์ฝ”๋“œ๊ฐ€ ์งง์•„์ง€๊ณ , ๋ชจ๋ธ๊ณผ ์„ค์ • ํด๋ž˜์Šค๊ฐ€ ํ•œ๋ˆˆ์— ๋ณด์—ฌ์„œ ๊ฐ€๋…์„ฑ์ด ์ข‹์•„์ง‘๋‹ˆ๋‹ค! โœ…


admin ์„ import ํ•˜๋ฉด ์ƒ๊ธฐ๋Š” ๊ฒƒ

http://localhost:8000/admin

โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”
โ”‚   Django ๊ด€๋ฆฌ์ž ํŽ˜์ด์ง€   โ”‚
โ”œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”ค
โ”‚ ๐Ÿ“‹ Study                โ”‚
โ”‚   + ์ถ”๊ฐ€                โ”‚
โ”‚   ๐Ÿ“ ๋ชฉ๋ก๋ณด๊ธฐ            โ”‚
โ”œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”ค
โ”‚ ๐Ÿ‘ค Users                โ”‚
โ”‚ ๐Ÿ”‘ Groups               โ”‚
โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”˜

์ด๊ฒŒ ๋‹ค ์ž๋™์œผ๋กœ ์ƒ์„ฑ! โœ…


settings.py ์™€์˜ ๊ด€๊ณ„

# settings.py
INSTALLED_APPS = [
    'django.contrib.admin',     # โ† ์—ฌ๊ธฐ ๋“ฑ๋ก๋˜์–ด ์žˆ์–ด์•ผ
    'django.contrib.auth',
    'django.contrib.sessions',
    ...
]

# ๊ทธ๋ž˜์•ผ admin.py ์—์„œ
from django.contrib import admin  # ์‚ฌ์šฉ ๊ฐ€๋Šฅ! โœ…

์ž์ฃผ ์“ฐ๋Š” contrib ๋ชจ์Œ

# ๊ด€๋ฆฌ์ž ํŽ˜์ด์ง€
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๊ฐ€์ ธ์™€
djangoDjango ํŒจํ‚ค์ง€์—์„œ
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 ์•ˆ์— ๋“ค์–ด์žˆ๋Š” ์ฃผ์š” ๋‚ด์žฅ ๊ธฐ๋Šฅ๋“ค

๐Ÿ“Œ ํ•„๋“œ (Field) โ€” ์ปฌ๋Ÿผ ํƒ€์ž… ์ •์˜

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 ๊ด€๊ณ„

๐Ÿ“Œ Model ํด๋ž˜์Šค โ€” ํ…Œ์ด๋ธ” ์ •์˜

class Study(models.Model):  # ์ด๊ฑธ ์ƒ์†๋ฐ›์•„์•ผ DB ํ…Œ์ด๋ธ”์ด ๋จ
    ...

๐Ÿ“Œ Meta ์˜ต์…˜ โ€” ๋ชจ๋ธ ์„ค์ •

class Study(models.Model):
    class Meta:
        ordering = ['-created_at']   # ๊ธฐ๋ณธ ์ •๋ ฌ
        db_table = 'my_study'        # ํ…Œ์ด๋ธ” ์ด๋ฆ„ ์ง€์ •
        verbose_name = '์Šคํ„ฐ๋””'       # ๊ด€๋ฆฌ์ž ํŽ˜์ด์ง€ ํ‘œ์‹œ๋ช…

์ž์ฃผ ์“ฐ๋Š” Django ๋‚ด์žฅ import ๋ชจ์Œ

# 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 ํ…Œ์ด๋ธ”๋กœ ๋ณ€ํ™˜ํ•  ์ˆ˜ ์žˆ์–ด์š”! ๐ŸŽฏ

profile
๊ฐœ๋ฐœ์–ธ์–ด๋ฅผ ๋ฐฐ์šฐ๋Š” ๊ณผ์ • ๊ธฐ๋ก

0๊ฐœ์˜ ๋Œ“๊ธ€