티스토리 뷰

Python/Django

Django 튜토리얼 part.2

cvcvcx9 2023. 5. 2. 20:25

1. 데이터베이스 설치

mysite/settings.py 를 연다. Django 설정을 변수로 표현한 Python 모듈이다.

  • 기본적으로 SQLite를 사용하도록 구성
  • 실제 프로젝트를 시작할 때는 PostgreSQL과 같은 확장성있는 데이터베이스 사용추천
  • 다른 데이터베이스 사용하고싶으면, 데이터베이스 바인딩 설치 후 Settings 값 변경

SQLite를 데이터베이스로 사용하지 않는 경우, USER, PASSWORD, HOST 와 같은 설정이 필요함

다른 데이터베이스를 사용할 경우 이 시점에 데이터베이스를 생성해야함

서버와 현재 지역의 시간을 맞춰주기 위해 TIME_ZONE을 설정해주는것을 추천

한국으로 설정하는 방법은 위와 같음 ( settings.py파일에서 TIME_ZONE항목에 Asia/seoul로 변경)

시간이 변경된것을 알 수 있음

INSTALLED_APPS

  • 현재 Django에서 활성화된 모든 어플리케이션의 이름이 담겨있음
  • 기본적으로 프로젝트를 생성하면 존재하는 목록은 아래와 같음
  1. django.contrib.admin - 관리용 사이트 프레임워크
  1. django.contrib.auth - 인증 시스템 프레임워크
  1. django.contrib.contenttypes - 컨텐츠 타입 확인용 프레임워크
  1. django.contrib.sessions- 세션 프레임워크
  1. django.contrib.messages - 메세징 프레임워크
  1. django.contrib.staticfile - 정적 파일을 관리하는 프레임워크

이 앱들중, 사용하기 위해서는 하나 이상의 데이터베이스 테이블을 사용

데이터베이스를 생성해야함

데이터베이스 생성

python manage.py migrate
  • settings 의 설정과 app 과 함께 제공되는 database migrations에 따라 필요한 데이터베이스 테이블을 생성하게됨
  • 위와같이 각 migration이 적용되는 메세지가 뜬 것을 확인 할 수 있음

2. 모델 만들기

모델 = 데이터 저장중인 데이터의 필수 필드 및 동작이 포함됨

Question 모델

  1. 질문 - question_text
  1. 발행일 -pub_date

Choice 모델

  1. 질문 -question
  1. 선택 텍스트 - choice_text
  1. 투표 집계 - votes
from django.db import models


class Question(models.Model):
#텍스트타입의 필드 생성 최대길이 200
    question_text = models.CharField(max_length=200)
#날짜와 시간 타입의 필드 생성, 첫번째 인자를 전달해서 사람이 읽기 좋은 설명을 달 수도 있음
#아래와 같은 경우 date published라는 설명이 달리게 됨
    pub_date = models.DateTimeField("date published")


class Choice(models.Model):
#Question 테이블을 외래키로 가진 필드 생성 - 만약 외래키가 삭제되면 영속성을 통해 같은 외래키를 지닌 모든 로우가 삭제됨
    question = models.ForeignKey(Question, on_delete=models.CASCADE)
    choice_text = models.CharField(max_length=200)
    votes = models.IntegerField(default=0)

  • models.Model을 상속한 클래스의 변수가 곧 데이터베이스의 필드가 됨
  • 즉, Question이라는 테이블, Choice라는 두개의 테이블이 생성됨
  • 또한, ForeignKey를 통해 테이블간의 관계에 대해 설정할 수 있음. 이 경우 ChoiceQuestion에 종속적이라고 볼 수 있음
  • max_length와 같은경우, 데이터베이스 설정에만 쓰이는게 아니라, 값을 검증할 때에도 쓰인다.

3. 모델의 활성화

장고는 이 코드를 가지고 다음과 같은 일들이 가능함

  • 데이터베이스 스키마 생성
  • QuestionChoice 객체에 접근하기 위한 Python 데이터베이스 접근 API 생성

이런 것들을 하기 위해서는 일단 polls앱을 settings에 추가해야함

settings.py

INSTALLED_APPS = [
    "polls.apps.PollsConfig", # 새로 추가된 app "polls"로도 추가가 됨


    "django.contrib.admin",
    "django.contrib.auth",
    "django.contrib.contenttypes",
    "django.contrib.sessions",
    "django.contrib.messages",
    "django.contrib.staticfiles",
]

추가 후

python manage.py makemigrations polls # 이 명령어로 적용할 쿼리문 생성
python manage.py sqlmigrate polls 0001 # 이 명령어로 생성된 쿼리문 출력
BEGIN;
--
-- Create model Question
--
CREATE TABLE "polls_question" (
    "id" bigint NOT NULL PRIMARY KEY GENERATED BY DEFAULT AS IDENTITY,
    "question_text" varchar(200) NOT NULL,
    "pub_date" timestamp with time zone NOT NULL
);
--
-- Create model Choice
--
CREATE TABLE "polls_choice" (
    "id" bigint NOT NULL PRIMARY KEY GENERATED BY DEFAULT AS IDENTITY,
    "choice_text" varchar(200) NOT NULL,
    "votes" integer NOT NULL,
    "question_id" bigint NOT NULL
);
ALTER TABLE "polls_choice"
  ADD CONSTRAINT "polls_choice_question_id_c5b4b260_fk_polls_question_id"
    FOREIGN KEY ("question_id")
    REFERENCES "polls_question" ("id")
    DEFERRABLE INITIALLY DEFERRED;
CREATE INDEX "polls_choice_question_id_c5b4b260" ON "polls_choice" ("question_id");

COMMIT;

위와 같이 자동으로 쿼리문이 생성된 것을 볼 수 있음

  • 테이블의 이름은 자동으로 앱이름_변수이름 이 된것을 볼 수 있음
  • 마지막 부분은 Foreignkey를 설정하는 부분임
  • 기본 키가 자동으로 추가됨(id)
  • ForeignKey 타입을 설정한 필드명의 경우 question_id 와 같이 뒤에_id 가 붙은것을 볼 수있음
  • 마지막으로, 아직 데이터베이스에 이 쿼리문이 적용된것이 아님. migrate명령어를 실행해야 적용됨

python manage.py migrate polls

4. 데이터베이스 가지고 놀기

이제 생성한 데이터베이스를 파이썬을 통해 가지고 놀아볼 수 있음

python manage.py shell #

python 명령어를 입력하는 대신 위 명령어를 사용하는 이유는 이 프로젝트의 가져오기 경로를 사용하기 위해서임

  1. 가지고 놀 Model 불러오기
  1. Model에 넣을 값 생성
  1. 데이터베이스에 적용
  1. 데이터베이스에 있는 값 수정하기

Model 불러오기

  • 모델을 사용하기 위해서는 모델을 불러와야함
  • manage.py로 shell을 실행했기때문에 경로는 프로젝트 내에서의 경로로 불러올 수 있음
from polls.models import Choice, Question #import 

Model에 있는 모든 값 가져오는 명령어

  • 이제 모델을 이용해서 데이터베이스에 있는 값을 다룰 수 있음
  • 맨 처음 해볼것은 조회
Question.objects.all() # Question 모델에 있는 모든 값을 보여줘
Out[2]: <QuerySet []> # 아무런 값이 들어있지 않기 때문에 빈 값이 나오게됨

새로운 값 데이터베이스에 집어넣기

  • 데이터베이스에 모델의 값을 집어넣음
  • 필요한 값은 현재 시간과 질문의 텍스트
# 현재 시간을 가져오기 위해 timezone import
from django.utils import timezone 

# 새로운 Question 객체를 생성 timezone의 now() 함수로 현재시간을 pub_date로 넣음
# 아직 데이터베이스에 저장 안됨!
q = Question(question_text = "What's new", pub_date = timezone.now())

# 이 명령어를 통해 데이터베이스에 값을 저장!
q.save()

# 아이디가 자동으로 생성된 것을 볼 수 있음!
q.id
out [3] : 1

위와 같이 값을 생성자를 통해 생성한뒤, 모델객체라면 존재하는 save함수를 통해 데이터베이스에 저장이 가능

수정하기

  • 데이터베이스에 이미 저장되어있는 값을 불러와서 수정
# q변수에 방금 데이터베이스에 저장한 객체 할당
q = Question.objects.first() 

# 제대로 할당되었는지 확인
q.id
out[19] : 1

# 값을 변경시켜봄
q.question_text = "안녕하세요?"

# 값이 변경되었는지 확인
q.question_text 
out[21] "안녕하세요?"

# 다시 데이터베이스에서 값을 조회 - 아직 변경 안된것을 알 수 있음
second = Question.objects.first()
second.question_text
Out[23]: "What's up?"

# 데이터베이스에 값을 저장

q.save()

# 데이터베이스에서 값을 다시 조회
second = Question.objects.first()
second.question_text
Out[23]: "안녕하세요?"

조건을 걸어 조회하기

.filter를 통해 조건을 걸 수 있다.

# 아래와 같이 __로 시작하는 조건비교를 filter lookups 라고 한다.
# 하단 링크로 가면 더 자세한 조건을 볼 수 있다.
Question.objects.filter(question_text__startswith="안녕")
Out[4]: <QuerySet [<Question: 안녕하세요?>]>

https://docs.djangoproject.com/ko/4.2/ref/models/querysets/#field-lookups

“__str__” 함수와 커스텀메소드 추가

from django.db import models


class Question(models.Model):
    # ...
    def __str__(self):
        return self.question_text


class Choice(models.Model):
    # ... java의 toString과 같은 함수라고 보면 됨 기본적으로 이 객체가 불릴때 어떤값을 보여줄지 결정
    def __str__(self):
        return self.choice_text
import datetime

from django.db import models
from django.utils import timezone


class Question(models.Model):
    # 지금 시간으로부터 하루 이내의 글인지 체크하는 함수
    def was_published_recently(self):
        return self.pub_date >= timezone.now() - datetime.timedelta(days=1)

  • 사용하기
In [5]: from django.utils import timezone

In [6]: current_year = timezone.now().year

In [7]: current_year
Out[7]: 2023
# 올해 만들어진 설문을 조회
In [8]: Question.objects.get(pub_date__year=current_year)
Out[8]: <Question: 안녕하세요?>

  • 값이 없는 경우
In [9]: Question.objects.get(id=2)
---------------------------------------------------------------------------
DoesNotExist                              Traceback (most recent call last)
Cell In[9], line 1
----> 1 Question.objects.get(id=2)

File ~/anaconda3/envs/py311/lib/python3.11/site-packages/django/db/models/manager.py:87, in BaseManager._get_queryset_methods.<locals>.create_method.<locals>.manager_method(self, *args, **kwargs)
     85 @wraps(method)
     86 def manager_method(self, *args, **kwargs):
---> 87     return getattr(self.get_queryset(), name)(*args, **kwargs)

File ~/anaconda3/envs/py311/lib/python3.11/site-packages/django/db/models/query.py:637, in QuerySet.get(self, *args, **kwargs)
    635     return clone._result_cache[0]
    636 if not num:
--> 637     raise self.model.DoesNotExist(
    638         "%s matching query does not exist." % self.model._meta.object_name
    639     )
    640 raise self.model.MultipleObjectsReturned(
    641     "get() returned more than one %s -- it returned %s!"
    642     % (
   (...)
    645     )
    646 )

DoesNotExist: Question matching query does not exist.

위와 같은 에러 발생

  • pk를 통한 조회
# pk를 통해서 조회한다. 장고는 많이쓰는 pk를 숏컷으로 만들었다. pk = 1이라는 문구는
# id=1이라는 문구를 동작시킨다.

In [10]: Question.objects.get(pk=1)
Out[10]: <Question: 안녕하세요?>
  • 커스텀 메서드
In [12]: q
Out[12]: <Question: 안녕하세요?>

In [13]: q.was_published_recently
Out[13]: <bound method Question.was_published_recently of <Question: 안녕하세요?>>

In [14]: q.was_published_recently()
Out[14]: True

위와같이 아까 모델에서 작성했던 was_published_recently()메서드를 사용할 수 있는것을 볼 수 있다.

ForeignKey로 관계 지정된 애들 불러오기

질문에는 여러개의 선택지가 있다.

지금 예시로 진행되고 있는 모델은 설문지를 토대로 만들어져있어서, 하나의 질문에 여러개의 선택지가 속해있는 형태이다.

아래와 같이 이 모델을 외래키로 관계지정시켜놓은 모델들을 불러올 수 있다.

q.choice_set.all() # 외래키로 지정한 모델명_set으로 모델들을 볼 수 있다.
Out[18]: <QuerySet []> # 하지만 이 질문에 선택지를 아무것도 안만들어놔서 비어있는 쿼리셋이 반환

_set.create

# _set.create로 이 모델을 외래키로 갖는 모델 생성가능
In [19]: q.choice_set.create(choice_text="안녕함")
Out[19]: <Choice: 안녕함>

In [20]: q.choice_set.create(choice_text="안녕못함")
Out[20]: <Choice: 안녕못함>

# 아래와 같이 두개의 Choice가 생성된 것을 볼 수 있음
In [21]: q.choice_set.all()
Out[21]: <QuerySet [<Choice: 안녕함>, <Choice: 안녕못함>]>

반대로 choice에서 question도 검색가능

In [22]: c = q.choice_set.first()

In [23]: c
Out[23]: <Choice: 안녕함>

In [24]: c.question
Out[24]: <Question: 안녕하세요?>

어드민페이지로 값 조작하기

  • 관리자 생성
  • 어드민 페이지 접속
  • 어드민 페이지에 모델 등록

관리자 생성

python manage.py createsuperuser # 어드민 페이지에 접속 가능한 유저 생성

# 이메일은 필수가 아님

어드민 페이지 접속

http://127.0.0.1/admin 으로 접속하면 로그인 페이지가 뜸

아까 생성했던 아이디와 비밀번호를 입력하면 다음과 같이 뜸

아직 모델을 등록하지 않아서 QuestionChoice가 보이지 않음

모델을 어드민페이지에 등록하기


# polls/admin.py

from django.contrib import admin

from .models import Question

admin.site.register(Question)

저장하면 아래와 같은 모습을 볼 수 있음

Questions로 들어가면 이렇게 보임

우측 상단의 ADD Question을 통해 질문을 추가할 수 있음

이 서식은 자동으로 Question 모델에서 생성이 됨

물론 수정도 삭제도 가능함

혹시 값을 누가 바꾸었는지 궁금하다면, 수정화면의 우측 상단의 히스토리를 통해 볼 수 있음

위와 같이 수정된 이력을 볼 수 있음


Uploaded by N2T

'Python > Django' 카테고리의 다른 글

vscode에서 장고 auto import를 하는법  (0) 2024.03.14
Django 클래스기반 뷰에서 쿼리셋 조작하기  (0) 2023.05.03
Django 튜토리얼 part.1  (0) 2023.05.02
Django 공식문서 튜토리얼 공부  (0) 2023.05.02
OneToOneField  (0) 2023.04.28
공지사항
최근에 올라온 글
최근에 달린 댓글
Total
Today
Yesterday
링크
«   2024/09   »
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
글 보관함