TIL - Django
๐ย ๊ณต๋ถ ๋ด์ฉ
Django ์ค์น ๋ฐ ๊ฐ๋ฐํ๊ฒฝ ์ค์
Python virtual environment (venv)
์๋ก ๋ค๋ฅธ ํ๊ฒฝ์์ ๊ฐ๋ฐ๋๋ ์ฌ๋ฌ ํ๋ก์ ํธ๋ฅผ ์งํํ ๋, ํ๊ฒฝ์ ์ฒดํฌํ๊ณ ๋ณ๊ฒฝํ๋ ๋ฒ๊ฑฐ๋ก์ ๋ฐ ํ๋ก์ ํธ๊ฐ์ ์ถฉ๋์ด ๋ฐ์ํ๋ค.
์ด์ ๊ฐ์ ๋ฌธ์ ์ ์ ๋ฐฉ์งํ๊ณ ํ๋ก์ ํธ๋ค์ ๊ฐ ๋ชฉ์ ์ ๋ง๊ฒ ํจ์จ์ ์ผ๋ก ๊ด๋ฆฌํ๊ธฐ ์ํด, ํ๋ก์ ํธ๋ง๋ค ๊ฐ์ํ๊ฒฝ์ ๋ง๋ค์ด ์ฌ์ฉํ๋๊ฒ์ ๊ถ์ฅํ๋ค.
- ๊ฐ์ํ๊ฒฝ ํ๋ก์ ํธ ์์ฑ
1
| $ python -m venv {project-name}
|
1
| $ source project-name/bin/activate
|
Django
๊ฐ์ํ๊ฒฝ์ด ํ์ฑํ ๋ ์ํ
์์ ์ค์น
Django ํ์ฉ
Django : ํ์ด์ฌ์ผ๋ก ์ ์๋ ์น ํ๋ ์์ํฌ
ํ๋ก์ ํธ
ํ๋ก์ ํธ ์์ฑ ๋ฐ ์๋ฒ ์คํ
1
2
| $ django-admin startproject mysite
$ python3 manage.py runserver
|
(python์ผ๋ก ์
๋ ฅํ๋ ๊ฒฝ์ฐ ์คํ์ด ๋์ง ์์ ๋๊ฐ ๋ง์ python3 ์ฌ์ฉ)
App & Url
- ์๋ก์ด ์ฑ
polls
์ index
, some_url
ํ์ด์ง๋ฅผ ์์ฑํ๊ณ url ์ฐ๊ฒฐ
1
| $ python3 manage.py startapp polls
|
1
2
3
4
5
6
7
| from django.http import HttpResponse
def index(request):
return HttpResponse("Hello, world.")
def some_url(request):
return HttpResponse("Some ulr์ ๊ตฌํํด ๋ดค์ต๋๋ค.")
|
1
2
3
4
5
6
7
| from django.contrib import admin
from django.urls import path, include
urlpatterns = [
path("admin/", admin.site.urls),
path("polls/", include('polls.urls'))
]
|
1
2
3
4
5
6
7
| from django.urls import path
from . import views
urlpatterns = [
path('',views.index, name='index')
path('some_url',views.some_url)
]
|
RDB Relational Database
๊ด๊ณํ ๋ฐ์ดํฐ๋ฒ ์ด์ค
๋ฐ์ดํฐ๋ฅผ ํ
๊ณผ ์ด
๋ก ์ด๋ฃจ์ด์ง ํ
์ด๋ธ
์ ํํ๋ก ๊ตฌ์ฑํ๊ณ , ํ
์ด๋ธ ๊ฐ์ ๊ด๊ณ
๋ฅผ ์ ์ํ๋ ๋ฐ์ดํฐ๋ฒ ์ด์ค
ํ
์ด๋ธ table
ํ๊ณผ ์ด๋ก ๊ตฌ์ฑ๋์ด ์๋ ๋ฐ์ดํฐ์ ์งํฉ
์ด column
ํ
์ด๋ธ์ ํ๋(field)
- primary key
- ํ
์ด๋ธ์ ๊ฐ ํ(row)์ ๊ณ ์ ํ๊ฒ ์๋ณํ ์ ์๋ ์ด(column)
- forien key
- ๋ค๋ฅธ ํ
์ด๋ธ์ primary key๋ฅผ ์ฐธ์กฐํ๋ ์ด(column)์ผ๋ก, ๋ ํ
์ด๋ธ ๊ฐ์ ๊ด๊ณ๋ฅผ ์ค์ ํ ์ ์์
ํ row
ํ
์ด๋ธ์ ์ ์ฅ๋ ๋ฐ์ดํฐ ๋ ์ฝ๋(Record)
Model
Django์์ RDB์ ์ฐ๋์ ๋ด๋นํ๋ ํด๋์ค๋ก, ๊ฐ ๋ชจ๋ธ์ ๋ฐ์ดํฐ๋ฒ ์ด์ค์ ํ
์ด๋ธ(Table)์ ํด๋นํ๋ฉฐ ํ๋(Field)๋ฅผ ๊ฐ์ง๊ณ ์๋ค.
- ๋ชจ๋ธ ํ๋ (model field)
- ๋ค์ํ ํ์
์ ํ๋์ ์ต์
์ด ์กด์ฌํ๋ค. ์์ธํ ์ค๋ช
์ ์๋ ๋งํฌ๋ฅผ ์ฐธ๊ณ .
- Django Model Fields
mysite/settings.py
1
2
3
4
5
6
7
8
9
10
11
12
13
| ...
# Application definition
INSTALLED_APPS = [
'django.contrib.admin',
'django.contrib.auth',
'django.contrib.contenttypes',
'django.contrib.sessions',
'django.contrib.messages',
'django.contrib.staticfiles',
'polls.apps.PollsConfig', #์๋ก ์์ฑํ app์ settings.py์ ์ถ๊ฐ
]
...
|
1
2
3
4
5
6
7
8
9
10
11
12
13
14
| from django.db import models
# polls app์ ๋ชจ๋ธ ๋ ๊ฐ๋ฅผ ๋ง๋ค๊ณ ๊ฐ๊ฐ์ field๋ฅผ ์ค์
# ๋ฐ๋ก primary key(=pk)๋ฅผ ์ค์ ํ์ง ์์ ๊ฒฝ์ฐ, ๋ชจ๋ธ์ด ์์ฑ๋ ๋ ์ฃผ์ด์ง๋ id์ ๊ฐ์ ๊ฐ์ ๊ฐ๊ฒ ๋จ
class Question(models.Model):
question_text = models.CharField(max_length=200)
pub_date = models.DateTimeField('date published')
# foreign key๋ก Question ๋ชจ๋ธ์ pk๋ฅผ ์ฐธ์กฐ
class Choice(models.Model):
question = models.ForeignKey(Question, on_delete=models.CASCADE)
choice_text = models.CharField(max_length=200)
votes = models.IntegerField(default=0)
|
1
| $ python3 manage.py makemigrations polls
|
- migration์ผ๋ก ์คํ๋ SQL ๋ฌธ์ฅ ์ดํด๋ณด๊ธฐ
1
| $ python3 manage.py sqlmigrate polls 0001
|
1
| $ python3 manage.py migrate
|
1
2
| #0001 ๋ฒ์ ์ผ๋ก ๋กค๋ฐฑ
$ python3 manage.py migrate polls 0001
|
Admin
๊ด๋ฆฌ์ ๊ณ์ ์ ์์ฑํ๊ณ ์น ๋ธ๋ผ์ฐ์ ๋ฅผ ํตํด ์ฌ์ดํธ์ ์ ์ํ์ฌ
User, App ๊ทธ๋ฆฌ๊ณ Model ๋ฑ์ ์์ฑ, ์์ ๋ฐ ์ญ์ ํ ์ ์๋ค.
1
| $ python manage.py createsuperuser
|
1
2
3
4
5
6
| from django.contrib import admin
from .models import * # polls/models.py ์์ ์ ์ํ ๋ชจ๋ธ์ ๊ฐ์ ธ์จ๋ค.
#admin site์ ์์ฑํ ๋ชจ๋ธ ๋ฑ๋ก
admin.site.register(Question)
admin.site.register(Choice)
|
1
2
3
4
5
6
7
8
9
10
11
12
13
14
| from django.db import models
class Question(models.Model):
question_text = models.CharField(max_length=200)
pub_date = models.DateTimeField('date published')
# field ์ถ๋ ฅ์ ์ํ ํจ์
def __str__(self):
return f'์ ๋ชฉ: {self.question_text}, ๋ ์ง: {self.pub_date}'
class Choice(models.Model):
question = models.ForeignKey(Question, on_delete=models.CASCADE)
choice_text = models.CharField(max_length=200)
votes = models.IntegerField(default=0)
|
Model Method
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
| from django.utils import timezone
import datetime
class Question(models.Model):
question_text = models.CharField(max_length=200)
pub_date = models.DateTimeField('date published')
def was_published_recently(self):
return self.pub_date >= timezone.now() - datetime.timedelta(days=1)
def __str__(self):
if self.was_published_recently():
new_badge = 'NEW!!!'
else:
new_badge = ''
return f'{new_badge} ์ ๋ชฉ: {self.question_text}, ๋ ์ง: {self.pub_date}'
|
QuerySet
List of model objects
๋ฐ์ดํฐ๋ฒ ์ด์ค๋ก๋ถํฐ ๋ฐ์ดํฐ๋ฅผ ์ฝ๊ณ , ํํฐ๋งํ๊ฑฐ๋ ์ ๋ ฌ
ํ ์ ์์
(Django Shell์์ ์งํ)
1
| $ python manage.py shell
|
Read model object
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
| # ๋ชจ๋ธ ๊ฐ์ ธ์ค๊ธฐ
>>> from polls.models import *
#๋ชจ๋ Question,Choice ์ค๋ธ์ ํธ ์ถ๋ ฅ
>>> Question.objects.all()
>>> Choice.objects.all()
#์ฒซ๋ฒ์งธ Choice ์ค๋ธ์ ํธ๋ฅผ ๊ฐ์ ธ์ ํ๋ ์ถ๋ ฅ
>>> choice = Choice.objects.all()[0]
>>> choice.id
>>> choice.choice_text
>>> choice.votes
#์ฒซ๋ฒ์งธ Choice์ ์ฐ๊ฒฐ๋ Question์ ๊ฐ์ ธ์ ํ๋ ์ถ๋ ฅ
>>> q = choice.question
>>> choice.question.pub_date
>>> choice.question.id
#ํด๋น Question๊ณผ ์ฐ๊ฒฐ๋์ด ์๋ ๋ชจ๋ Choice ๊ฐ์ ธ์ค๊ธฐ
>>> q.choice_set.all()
|
CRUD model objects (Records)
(CRUD : Create, Read, Update & Delete)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
| >>> from polls.models import *
# ์๋ก์ด Question ์ค๋ธ์ ํธ๋ฅผ ๋ด์ฉ๊ณผ ํจ๊ป ์์ฑํ๊ณ 'q1'์ด๋ผ๋ ๋ณ์์ ์ ์ฅ
>>> q1 = Question(question_text = "์ปคํผ vs ๋
น์ฐจ")
# 'q1' ์์ฑ์๊ฐ์ ์ค์
>>> from django.utils import timezone
>>> q1.pub_date = timezone.now()
# 'q1'์ ๋ฐ์ดํฐ๋ฒ ์ด์ค์ ์ ์ฅํ๊ธฐ
>>> q1.save()
# ๊ฐ์ ๊ณผ์ ์ ํตํด q2๋ฅผ ์์ฑํ๊ณ ๋ฐ์ดํฐ๋ฒ ์ด์ค์ ์ ์ฅ
>>> q2 = Question(question_text = "abc")
>>> q2.pub_date = timezone.now()
>>> q2.save()
# .create method๋ก Choice object๋ฅผ ์์ฑํ์ฌ q2์ ์ฐ๊ฒฐ
>>> q2.choice_set.create(choice_text = "b")
# Choice object๋ฅผ ์์ฑํ ๋ question field์ q2๊ฐ์ ๋ฃ์ด ์ฐ๊ฒฐ
>>> choice_c = Choice(choice_text='c', question=q3)
#์๋ก์ด Choice ์ค๋ธ์ ํธ๋ฅผ ๋ฐ์ดํฐ๋ฒ ์ด์ค์ ์ ์ฅํ๊ธฐ
>>> choice_c.save()
# q2์ ์ฐ๊ฒฐ๋ Choice ์ค๋ธ์ ํธ๋ค์ ํ์ธ
>>> q2.choice_set.all()
<QuerySet [<Choice: b>, <Choice: c>]>
# ๊ฐ์ฅ ๋ง์ง๋ง์ผ๋ก ์์ฑ๋ ์ค๋ธ์ ํธ ๊ฐ์ ธ์ ์ญ์ ํ๊ธฐ
>>> q = Question.objects.last()
>>> q.delete()
|
Filter model objects
1
2
3
4
5
6
| # ์กฐ๊ฑด์ ๋ง๋ ์ค๋ธ์ ํธ ํํฐ๋ง
>>> Question.objects.get(id=1)
>>> Question.objects.get(question_text__startswith='ํด๊ฐ๋ฅผ')
# ์ค๋ธ์ ํธ ์ฌ๋ฌ๊ฐ๋ฅผ ๋ฐํํ๋ ํํฐ๋ง์ ์งํํ ๊ฒฝ์ฐ ์๋ฌ ๋ฐ์
>>> Question.objects.get(pub_date__year=2023)
# get() returned more than one Question
|
- QuerySet method
filter() & exclude()
1
2
3
4
5
6
7
8
9
10
| # ์ฌ๋ฌ ์ค๋ธ์ ํธ๋ฅผ ๋ฐํํ๋ ํํฐ๋ง ๊ฐ๋ฅ
>>> Question.objects.filter(pub_date__year=2023)
<QuerySet [<Question: ์ ๋ชฉ: ํด๊ฐ๋ฅผ ์ด๋์ ๋ณด๋ด๊ณ ์ถ์ผ์ธ์?, ๋ ์ง: 2023-02-05 18:52:59+00:00>, <Question: ์ ๋ชฉ: ๊ฐ์ฅ ์ข์ํ๋ ๋์ ํธ๋?, ๋ ์ง: 2023-02-05 18:53:27+00:00>, ...]>
>>> Question.objects.filter(pub_date__year=2023).count()
2
# ๊ด๊ณ๊ธฐ๋ฐ์ ํํฐ๋ง
# foreign key๋ก ์ง์ ๋ Model์ ํ๋๊ฐ์ผ๋ก ํํฐ๋ง ๊ฐ๋ฅ
>>> Choice.objects.filter(question__question_text__startswith='ํด๊ฐ')
>>> Choice.objects.exclude(question__question_text__startswith='ํด๊ฐ')
|
1
2
3
4
5
6
7
8
9
| # example 1
>>> print(Question.objects.filter(pub_date__year=2023).query)
SELECT "polls_question"."id", "polls_question"."question_text", "polls_question"."pub_date" FROM "polls_question" WHERE "polls_question"."pub_date" BETWEEN 2023-01-01 00:00:00 AND 2023-12-31 23:59:59.999999
# example 2
# pk == primary key = id
>>> q = Question.objects.get(pk=1)
>>> print(q.choice_set.all().query)
SELECT "polls_choice"."id", "polls_choice"."question_id", "polls_choice"."choice_text", "polls_choice"."votes" FROM "polls_choice" WHERE "polls_choice"."question_id" = 1
|
QuerySet methods filter()
, exclude()
& get()
์์ keyword arguments
๋ก ์ง์ ๋จ
1
2
3
4
5
6
7
8
9
10
11
12
| # startswith
>>> Question.objects.filter(question_text__startswith='ํด๊ฐ๋ฅผ')
# contains
>>> Question.objects.filter(question_text__contains='ํด๊ฐ')
# gt, gte, lt, lte
>>> Choice.objects.filter(votes__gt=0)
# ์ ๊ทํํ์
>>> print(Question.objects.filter(question_text__regex=r'^ํด๊ฐ.*์ด๋').query)
SELECT "polls_question"."id", "polls_question"."question_text", "polls_question"."pub_date", "polls_question"."owner_id" FROM "polls_question" WHERE "polls_question"."question_text" REGEXP ^ํด๊ฐ.*์ด๋
|
- datetime
- date : ๋ ์ง๋ฅผ ๋ค๋ฃจ๊ธฐ ์ํ ํด๋์ค(Year, Month, Day)
- time : ์๊ฐ์ ๋ค๋ฃจ๊ธฐ ์ํ ํด๋์ค(Hour, Minute, Second, Microsecond)
- datetime : ๋ ์ง์ ์๊ฐ์ ๋ค๋ฃจ๊ธฐ ์ํ ํด๋์ค (date ํด๋์ค์ time ํด๋์ค์ ์์ฑ์ ๋ชจ๋ ๊ฐ์ง)
- timedelta : ์๊ฐ ๊ฐ๊ฒฉ์ ๋ค๋ฃจ๊ธฐ ์ํ ํด๋์ค
1
2
3
4
5
6
7
8
9
| from datetime import datetime, timedelta
now = datetime.now()
# one hour / one day / one week / one year later
hour_after = now + timedelta(hours=1)
day_after = now + timedelta(days=1)
week_after = now + timedelta(days=7) # weeks=1
year_after = now + timedelta(days=365)
|
- timezone
- UTC ์ ๋ณด๋ฅผ ํฌํจํ๋ฉฐ, ๊ธฐ๋ณธ๊ฐ์
UTC+0
1
2
3
4
| from django.utils import timezone
now = timezone.now()
# datetime.datetime(2023, 10, 28, 6, 25, 23, tzinfo=datetime.timezone.utc)
|
๐ย CHECK
(์ด๋ ต๊ฑฐ๋ ์๋กญ๊ฒ ์๊ฒ ๋ ๊ฒ ๋ฑ ๋ค์ ํ์ธํ ๊ฒ๋ค)
โ ๋๋ ์
์ค๋์ Django ํ๋ ์์ํฌ์ ์๊ฐ ๋ฐ ๊ธฐ๋ณธ ๊ธฐ๋ฅ๊ณผ ๊ตฌ์กฐ์ ๋ํด ๋ฐฐ์ ๋ค. ๊ฐ๋จํ ๊ฐ๋
๋ฐ ์๊ฐ์๊ธฐ ๋๋ฌธ์ ์ด๋ ต๋ค๊ธฐ ๋ณด๋ค๋ ์ ๋ฆฌํ๊ณ ๊ธฐ์ตํด์ผ ํ ๋ด์ฉ์ด ๋ง์ ๊ณต๋ถํ๊ณ ์ ๋ฆฌํ๋ ๋ฐ ์ค๋ ์๊ฐ์ด ๋ค์๋ค.
์ค๋ ๊ณต๋ถํ ๊ธฐ๋ณธ์ ์ธ ๊ฐ๋
์ ์ ์ ๋ฆฌํ๊ณ ์ถ์ด์ ๊ฐ์๋ฅผ ๋ค์ ์๊ฐ๋งํผ TIL์ ์ ์๋ค. 100% ๋ง์กฑํ์ง ๋ชปํด๋ ๋ด๊ฐ ์ ๋ฆฌํ ๋ด์ฉ๊ณผ ๊ณต์ document๋ฅผ ํตํด ๋ฐ๋ก ์ฐพ์๋ณธ ๋ด์ฉ๋ค์ ๊ธฐ๋ฐ์ผ๋ก ์ ์ด์ ๋ฟ๋ฏํ๋ค. ์ค๋ ์ ๋ฆฌํ๋๊ฒ ์ ๋ง ํ๋ค์์ง๋ง ์ด ๊ฒฝํ ๋๋ถ์ ์ดํ ๊ฐ์๋ค์ ์ ์ดํดํ ์ ์์๊ฑฐ๋ผ๊ณ ๋ณธ๋ค.
๋ชจ๋ฅด๋ ๋ด์ฉ์ ์ฐพ์๋ณด๊ณ ์ ์ฉํ๋๋ด ์์ ์ด ์์ง๋ง ๋จ๋ค์ด ์ดํดํ ์ ์๊ฒ ์ ๋ฆฌํ๋๋ด ์ ๋ง ์์ ์ด ์๋ค. (๋ง๋ก ์ค๋ช
ํ๋๊ฒ๋ ๋น์ทํ ํธ์ด๋ค.) ๊ทธ๋๋ TIL์ ์ ๊ธฐ ์ ๋ณด๋ค๋ ํจ์ฌ ๋์์ก๋ค๋ ๊ฑธ ์ค์ค๋ก๋ ์ฒด๊ฐ์ค์ด๋ค. ์ ๋ฆฌํ๋๋ฐ ๋ค์ธ ์๊ฐ๋ค์ด ๊ฑฐ๋ฆ์ด ๋์ด ๋์ค์๋ ‘์ ์ดํด๋๋ ๊ธ’, ‘์ ์ค๋ช
ํ ๊ธ’ ์ด๋ผ๋ ์ข์ ๊ฒฐ๊ณผ๋ฅผ ์ํํ ์ ์๊ธฐ๋ฅผ!!