다음 순서에 따라 환경을 설정합니다.
cd dir-name
)에서 py -m venv project-name
명령어 실행(파이썬 가상환경 생성).project-name\Scripts\activate.bat
명령어로 해당 가상환경 활성화.py -m pip install Django
명령어로 Django 설치 및 django-admin version
명령어로 설치 확인.django-admin startproject project-name
명령어로 장고 프로젝트 만들기.python manage.py runserver
명령어로 해당 프로젝트 서버에서 실행하기.manage.py는 터미널에서 장고를 제어하기 위한 파일입니다.
다음 순서에 따라 명령어를 입력합니다. (커맨드 창을 켜놓고 파일을 수정하면, 커맨드 창에서 수정된 결과에 대해 반환된 것을 확인할 수가 있습니다.)
python manage.py startapp polls(앱이름)
명령어로 앱 생성.from django.contrib import admin
from django.urls import path, include
# urlpatterns에 있는 url이 들어올 경우, 해당하는 파일로 보낸다.
urlpatterns = [
path("admin/", admin.site.urls),
path("polls/", include('polls.urls')),
]
from django.urls import path
from . import views
urlpatterns = [
# url이 비어서 들어올 경우(예, 127.0.0.1:8000/polls or 127.0.0.1:8000/polls/)
# 해당 처리를 views.index로 보내며, 해당 이름은 'index'로 한다.
path('', views.index, name='index'),
]
from django.http import HttpResponse
def index(request):
# 요청이 들어오면 "Hello World."를 리턴한다.
return HttpResponse("Hello World.")
from django.urls import path
from . import views
urlpatterns = [
path('', views.index, name="index"),
path('some_url', views.some_url),
]
from django.http import HttpResponse
def index(request):
return HttpResponse("Hello World.")
def some_url(request):
return HttpResponse("Some URL !!")
실제 웹 사이트의 경우, 위의 예시처럼 정적인 웹 페이지를 리턴하는 것이 아니라 동적으로 웹 페이지를 구성합니다. 이러한 작업을 하기 위해서는 DB에서 값을 읽어들여 이를 출력해야 합니다.
장고의 ("models.py"파일의) 모델은 DB를 테이블 별로 읽어서 값을 코드로 읽어주는 역할을 합니다. 이를 ORM이라고 부르기도 합니다.
절차는 크게 다음과 같습니다.
구체적인 절차는 다음과 같습니다.
from django.db import models
# Create your models here.
# 모델 생성 -> 마이그레이션 생성(setting.py 설정) -> 모델에 대한 테이블 생성
# 질문: 어디로 놀러 가고 싶니?
# 대답: 산, 강, 바다, 도심 호캉스
# 질문 모델
class Question(models.Model):
question_text = models.CharField(max_length=200) # 텍스트를 저장하는 필드
pub_date = models.DateTimeField('date published') # 날짜를 저장하는 필드
# 대답 모델
class Choice(models.Model):
question = models.ForeignKey(Question, on_delete=models.CASCADE) # 외래키 Question을 CASCADE로 참조한다.
choice_text = models.CharField(max_length=200) # 텍스트를 저장하는 필드 (산, 강, ..)
votes = models.IntegerField(default=0) # 숫자를 저장하는 필드 (투표 개수)
INSTALLED_APPS = [
'django.contrib.admin',
'django.contrib.auth',
'django.contrib.contenttypes',
'django.contrib.sessions',
'django.contrib.messages',
'django.contrib.staticfiles',
'polls.apps.PollsConfig', # 추가된 앱
]
터미널에서 python manage.py makemigrations polls
명령어로 polls라는 이름의 마이그레이션 파일 생성하기. => 'polls'에 대해서 Question과 Choice라는 모델을 만드는 migration을 생성합니다.
python manage.py sqlmigrate polls 0001
명령어로 SQL 문장 확인하기=> "id" integer NOT NULL PRIMARY KEY AUTOINCREMENT 를 보면, 장고에서는 자동으로 테이블을 만들 때, id 필드를 생성한다는 것을 알 수 있습니다.
그리고, CREATE INDEX "~~~" ON "polls_choice" ("question_id")를 보면, 장고는 Question의 id에 대해서 인덱싱하고 있음을 알 수 있습니다. 이를 활용해서 예시로 "quetion 1에 대한 choice들을 바로 찾을 수 있습니다." (Choice 모델은 Question 모델을 ForeignKey로 참조하고 있기에 이런 일이 발생합니다.)
python manage.py migrate
명령어로 마이그레이션 실행하기.
django의 공식 document 사이트 https://docs.djangoproject.com/en/4.2/
에서 model layer 영역에서 Filed types에서 여러 가지 필드들에 대한 정보를 알 수가 있습니다. 다음은 몇 가지 예시입니다.
다음은 question 모델에 필드를 추가했다가 다시 삭제하는 예시입니다.
from django.db import models
# Create your models here.
# 모델 생성 -> 마이그레이션 생성(setting.py 설정) -> 테이블 생성
# 질문 어디로 놀러 가고 싶니?
# 대답: 산, 강, 바다, 도심 호캉스
# 질문
class Question(models.Model):
question_text = models.CharField(max_length=200) # 텍스트를 저장하는 필드
pub_date = models.DateTimeField('date published') # 날짜를 저장하는 필드
is_something = models.BooleanField(default=False) # 추가된 필드
average_score = models.FloatField(default=0.0) # 추가된 필드
# 대답
class Choice(models.Model):
question = models.ForeignKey(Question, on_delete=models.CASCADE) # 외래키 Question을 CASCADE로 참조한다.
choice_text = models.CharField(max_length=200) # 텍스트를 저장하는 필드
votes = models.IntegerField(default=0) # 숫자를 저장하는 필드
sqlite3 db.sqlite3
명령어로 SQL 창 실행하기. 만약 sqlite3 명령어 실행이 되지 않는다면 https://www.sqlite.org/download.html 에서 sqlite를 설치하여 sqlite3.ext 파일을 해당 디렉토리로 위치시킵니다.
SQL 창에서 .tables
명령어로 table 목록 확인하기.
SELECT* FROM django_migrations;
명령어로 로그 확인하기.
=> 맨 아래, polls|0002_question~~ 를 보면, 새로운 migrations 0002에 대한 로그를 확인할 수가 있습니다.
.schema polls_question
명령어로 polls_question에 대한 스키마 확인하기.
=> 위에서 수정했던 필드들에 대한 스키마가 추가된 것을 확인할 수가 있습니다.
이제 다시 삭제해보겠습니다. python manage.py migrate polls 0001
명령어로 0001버전(이전 버전)으로 롤백하기.
polls/models.py에서 수정된 내용 반영하기.
from django.db import models
# Create your models here.
# 모델 생성 -> 마이그레이션 생성(setting.py 설정) -> 테이블 생성
# 질문 어디로 놀러 가고 싶니?
# 대답: 산, 강, 바다, 도심 호캉스
# 질문 모델
class Question(models.Model):
question_text = models.CharField(max_length=200) # 텍스트를 저장하는 필드
pub_date = models.DateTimeField('date published') # 날짜를 저장하는 필드
# 삭제된 필드
# is_something = models.BooleanField(default=False)
# average_score = models.FloatField(default=0.0)
# 대답 모델
class Choice(models.Model):
question = models.ForeignKey(Question, on_delete=models.CASCADE) # 외래키 Question을 CASCADE로 참조한다.
choice_text = models.CharField(max_length=200) # 텍스트를 저장하는 필드
votes = models.IntegerField(default=0) # 숫자를 저장하는 필드
CRUD란, Create, Read, Update, Delete라는 의미로, 개발 관련하여 자주 등장하는 용어입니다.
CURD를 수행하는 Admin 계정은 다음과 같이 생성합니다.
python manage.py createsuperuser
명령어를 실행한 뒤, 계정 이름 및 패스워드를 입력.
"http://127.0.0.1:8000/admin/" 에서 계정 이름 및 패스워드 입력.
로그인 후, 다음 화면에서도 User를 추가 및 관리할 수가 있습니다. Add를 클릭한 후, 새로운 유저 admin2를 생성한 후, 해당 admin2를 클릭하여 permissions에서 권한을 설정할 수도 있습니다.
from django.contrib import admin
from .models import *
# Register your models here.
admin.site.register(Question)
admin.site.register(Choice)
POLLS에서 모델 옆의 Add 버튼 클릭.
필드값 입력 후 save.
polls/models.py 파일에서 Question에 대한 출력 양식 입력하기.
from django.db import models
# Create your models here.
# 모델 생성 -> 마이그레이션 생성(setting.py 설정) -> 테이블 생성
# 질문 어디로 놀러 가고 싶니?
# 대답: 산, 강, 바다, 도심 호캉스
# 질문 모델
class Question(models.Model):
question_text = models.CharField(max_length=200) # 텍스트를 저장하는 필드
pub_date = models.DateTimeField('date published') # 날짜를 저장하는 필드
# is_something = models.BooleanField(default=False)
# average_score = models.FloatField(default=0.0)
#해당 질문 모델을 출력할 때, question_text를 출력.
def __str__(self):
return f'제목: {self.question_text}, 날짜: {self.pub_date}'
# 대답 모델
class Choice(models.Model):
question = models.ForeignKey(Question, on_delete=models.CASCADE) # 외래키 Question을 CASCADE로 참조한다.
choice_text = models.CharField(max_length=200) # 텍스트를 저장하는 필드
votes = models.IntegerField(default=0) # 숫자를 저장하는 필드
from django.db import models
# Create your models here.
# 모델 생성 -> 마이그레이션 생성(setting.py 설정) -> 테이블 생성
# 질문 어디로 놀러 가고 싶니?
# 대답: 산, 강, 바다, 도심 호캉스
# 질문 모델
class Question(models.Model):
question_text = models.CharField(max_length=200) # 텍스트를 저장하는 필드
pub_date = models.DateTimeField('date published') # 날짜를 저장하는 필드
# is_something = models.BooleanField(default=False)
# average_score = models.FloatField(default=0.0)
# 추가된 필드
score = models.FloatField(default=0)
is_something_wrong = models.BooleanField(default=False)
json_field = models.JSONField(default=dict)
#해당 질문 모델을 출력할 때, question_text를 출력.
def __str__(self):
return f'제목: {self.question_text}, 날짜: {self.pub_date}'
# 대답 모델
class Choice(models.Model):
question = models.ForeignKey(Question, on_delete=models.CASCADE) # 외래키 Question을 CASCADE로 참조한다.
choice_text = models.CharField(max_length=200) # 텍스트를 저장하는 필드
votes = models.IntegerField(default=0) # 숫자를 저장하는 필드
=> 여러 필드에 대한 입력 폼을 확인할 수가 있습니다.
python manage.py shell
명령어로 Django Shell을 열기.
from polls.models import *
후, Question 실행해 보기.
모델이름.objects.all()
명령어로 테이블 확인하기.
관리자 페이지에서 choice 레코드 추가하기.
polls/models.py 에서 Choice 모델에 대한 출력 양식 설정하기.
# 대답 모델
class Choice(models.Model):
question = models.ForeignKey(Question, on_delete=models.CASCADE) # 외래키 Question을 CASCADE로 참조한다.
choice_text = models.CharField(max_length=200) # 텍스트를 저장하는 필드
votes = models.IntegerField(default=0) # 숫자를 저장하는 필드
def __str__(self):
return f'{self.choice_text}'
Choice 확인하기.
Choice 객체에 대한 여러 정보 확인하기 및 question 참조하기. choice.OOO
Question에서 Choice 참조하기. question.choice_set.all()
Django에서는 time zone 정보를 확인해야 합니다. 많은 웹서비스는 글로벌하게 이용되기 때문에 time zone 정보가 필요합니다.
따라서, Django에서는 Python의 datetime 대신에 timezone 을 사용합니다.
from django.utils import timezone
timezone.now()
=> time zone에 대한 정보도 있는 것을 확인할 수가 있습니다.
방법 1, 모델 객체 생성 후 저장하기.)
모델 객체 생성하기. q1 = Question(quetion_text = "coffee vs tea", pub_date = timezone.now())
해당 객체를 DB에 저장하기. q1.save()
polls/models.py 에서 pub_date 필드에 대한 옵션 변경하기.
class Question(models.Model):
question_text = models.CharField(max_length=200)
# auto_now=True : 해당 모델이 갱신될 때마다, 현재의 시각 정보 저장.
# auto_now_add=True : 해당 모델이 생성될 때, 현재의 시각 정보 저장.
pub_date = models.DateTimeField(auto_now_add=True)
def __str__(self):
return f'제목: {self.question_text}, 날짜: {self.pub_date}'
방법 2-1, 저장되어 있는 모델 객체에서 바로 생성하기)
q3 = Question(question_text="abc")
q3.save()
q3.choice_set.create(choice_text='a')
q3.choice_set.create(choice_text='b')
방법 2-2)
choice_c = Choice(choice_text='c', question=q3)
choice_c.save()
q.question_text = q.question_text + "???"
choice.delete()
Quetion.objects.get(id=1)
Quetion.objects.get(question_text__startswith='휴가를')
Quetion.objects.get(pub_date__year=2023)
Question.objects.filter(pub_date__year=2023)
Question.objects.filter(pub_date__year=2023).count()
: 해당되는 객체들의 총 개수 반환print(Question.objects.filter(question_text__startswith='휴가를').query)
이 외에도 https://docs.djangoproject.com/en/4.2/ref/models/querysets/의 field-lookups 에서 여러 필터링 조건들에 대해서 확인할 수가 있습니다.
>>> Question.objects.filter(question_text__contains='휴가')
<QuerySet [<Question: 제목: 휴가를 보내고 싶은 장소는?, 날짜: 2023-10-30 06:32:04+00:00>, <Question: 제목: 휴가를 가실 계획인 가요?, 날짜: 2023-10-30 08:39:36.707623+00:00>]>
>>> print(Choice.objects.filter(votes__gt=0).query)
SELECT "polls_choice"."id", "polls_choice"."question_id", "polls_choice"."choice_text", "polls_choice"."votes" FROM "polls_choice" WHERE "polls_choice"."votes" > 0
>>> Choice.objects.filter(votes__gt=0).update(votes=0)
1 //업데이트된 레코드 수 반환.
>>> Choice.objects.filter(votes=0).delete()
(4, {'polls.Choice': 4}) //삭제된 레코드 수 반환.
>>> Question.objects.filter(question_text__regex=r'^휴가.*장소')
<QuerySet [<Question: 제목: 휴가를 보내고 싶은 장소는?, 날짜: 2023-10-30 06:32:04+00:00>]>
>>> print(Question.objects.filter(question_text__regex=r'^휴가.*장소').query)
SELECT "polls_question"."id", "polls_question"."question_text", "polls_question"."pub_date" FROM "polls_question" WHERE "polls_question"."question_text" REGEXP ^휴가.*장소
-----------------------------------------------------------------------------
위와 같은 결과 출력.
>>> Question.objects.filter(question_text__startswith='휴가').filter(question_text__contains='장소')
<QuerySet [<Question: 제목: 휴가를 보내고 싶은 장소는?, 날짜: 2023-10-30 06:32:04+00:00>]>
>>> print(Question.objects.filter(question_text__startswith='휴가').filter(question_text__contains='장소').query)
SELECT "polls_question"."id", "polls_question"."question_text", "polls_question"."pub_date" FROM "polls_question" WHERE ("polls_question"."question_text" LIKE 휴가% ESCAPE '\' AND "polls_question"."question_text" LIKE %장소% ESCAPE '\')
>>> Question.objects.exclude(question_text__startswith='휴가')
<QuerySet [<Question: 제목: 가장 좋아하는 음식은?, 날짜: 2023-10-30 06:32:40+00:00>, <Question: 제목: coffee vs tea, 날짜: 2023-10-30 07:42:55.452696+00:00>]>
from django.utils import timezone
import datetime
class Question(models.Model):
question_text = models.CharField(max_length=200)
pub_date = models.DateTimeField(auto_now_add=True)
# 생성 날짜가 최근 1일 이내인지 확인하는 메서드
def was_published_recently(self):
return self.pub_date >= timezone.now() - datetime.timedelta(days=1)
#해당 질문 모델을 출력할 때, question_text를 출력.
def __str__(self):
if self.was_published_recently():
new_badge = "New!!!"
else:
new_badge = ''
return f'{new_badge} 제목: {self.question_text}, 날짜: {self.pub_date}'