[Django] 설문조사 앱 만들기 part.2

Jungmin Seo·2021년 6월 17일
0

데이터베이스 설치

mysite/settings.py django 설정을 모듈 변수로 표현한 모듈

기본적으로 SQLite를 사용하도록 구성되어 있다. (기본적으로 제공되기 때문에 설치할 필요 X)

다른 데이터베이스를 사용할 경우,
1. 적절한 데이터베이스 바인딩을 설치 (MySQL - sqlclient)
2. DATABASES 'default' 항목의 값을 다음의 키 값으로 바꾼다.

  • ENGINE – django.db.backends.sqlite3, django.db.backends.postgresql, django.db.backends.mysql, 또는 django.db.backends.oracle. 그외에 서드파티 백엔드 참조.
  • NAME – The name of your database. If you’re using SQLite, the database will be a file on your computer; in that case, NAME should be the full absolute path, including filename, of that file. The default value, BASE_DIR / 'db.sqlite3', will store the file in your project directory.

예시

DATABASES = {
    'default': {
        'ENGINE': 'django.db.backends.postgresql',
        'NAME': 'mydatabase',
        'USER': 'mydatabaseuser',
        'PASSWORD': 'mypassword',
        'HOST': '127.0.0.1',
        'PORT': '5432',
    }
}

데이터베이스 추가 설정 참고
https://docs.djangoproject.com/ko/3.1/ref/settings/#std:setting-DATABASES


settings.py 편집

INSTALLED_APPS

아래 앱들은 기본으로 제공된다.
필요하지 않은 항목은 migrate 실행하기 전에 주석처리하거나 삭제해도 무방하다.

django.contrib.admin 관리용 사이트
django.contrib.auth 인증 시스템
django.contrib.contenttypes 컨텐츠 타입을 위한 프레임워크
django.contrib.sessions 세션 프레임워크
django.contrib.messages 메세징 프레임워크
django.contrib.staticfiles 정적파일을 관리하는 프레임워크

+) mysite/settings.py를 편집할 때, 본인의 시간대에 맞춰 TIME_ZONE 값을 설정한다.

migrate 실행해준다.

$ python manage.py migrate

Migrations: 모델에 생긴 변화(필드추가, 모델삭제 등)를 반영하는 django의 방식

  • migrate 아직 적용되지 않은 migration을 모두 수집해서 실행할 때
  • makemigrations 새로운 migrations을 만들 때
  • sqlmigrate migration을 sql 구문으로 볼 때
  • showmigrations 프로젝트의 migration과 상태를 리스트업할 때

모델 만들기

모델은 데이터의 필수적인 필드들과 동작들을 포함한다.

# polls/models.py


from django.db import models

class Question(models.Model):
    question_text = models.CharField(max_length=200)
    pub_date = models.DateTimeField('date published')

class Choice(models.Model):
    # Question 모델을 ForeignKey로 참조한다
    question = models.ForeignKey(Question, on_delete=models.CASCADE)
    choice_text = models.CharField(max_length=200)
    votes = models.IntegerField(default=0)

데이터베이스의 각 필드는 Field 클래서의 인스턴스로 표현된다.
CharField 문자필드 (필수 인수: max_length)
DateTimeField 날짜와 시간 필드
선택적 인수로는 default 등이 있고, ForeinKey로 관계설정이 가능하다.


모델의 활성화

현재 프로젝트에게 polls 앱이 설치되어 있다는 것을 알려준다.
앱을 현재의 프로젝트에 포함시키기 위해서는, 앱의 구성 클래스에 대한 참조를 INSTALLED_APPS 설정에 추가해야 한다.

# mysite/settings.py

INSTALLED_APPS = [
    'polls.apps.PollsConfig',    # PollsConfig 클래스를 경로로 추가
    'django.contrib.admin',
    'django.contrib.auth',
    'django.contrib.contenttypes',
    'django.contrib.sessions',
    'django.contrib.messages',
    'django.contrib.staticfiles',
]

모델의 변경사항을 django에 알리고 migration(0001)이 저장되었다.
$ python manage.py makemigrations polls


SQL 문장으로 확인해본다.

$ python manage.py sqlmigrate polls 0001
BEGIN;
--
-- Create model Question
--
CREATE TABLE "polls_question" (
    "id" serial NOT NULL PRIMARY KEY,
    "question_text" varchar(200) NOT NULL,
    "pub_date" timestamp with time zone NOT NULL
);
--
-- Create model Choice
--
CREATE TABLE "polls_choice" (
    "id" serial NOT NULL PRIMARY KEY,
    "choice_text" varchar(200) NOT NULL,
    "votes" integer NOT NULL,
    "question_id" integer 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;

  • 테이블 이름은 앱의 이름과 모델의 이름(소문자)이 조합되어 자동으로 생성된다.
    ex. polls_question, polls.choice
  • 관례에 따라, django는 외래 키 필드명"_id" 이름을 자동으로 추가한다.
  • 위 두 가지는 모두 재지정 가능하다.

이제 migration을 실행/적용 시켜준다.

$ python manage.py migrate

Operations to perform:
  Apply all migrations: admin, auth, contenttypes, polls, sessions
Running migrations:
  Rendering model states... DONE
  Applying polls.0001_initial... OK


Python Shell에서 Django API 사용하기

$ python manage.py shell

데이터베이스 API

>>> from polls.models import Choice, Question

>>> Question.objects.all()    # Question 클래스의 객체 보기
<QuerySet []>  

>>> from django.utils import timezone
>>> q = Question(question_text="What's new?", pub_date=timezone.now())

>>> q.save()    # 위에서 생성한 object인 q 저장
>>> q.id    # 저장했으므로 id를 가짐
1

# object field value 알아보기
>>> q.question_text    
"What's new?"
>>> q.pub_date
datetime.datetime(2012, 2, 26, 13, 0, 0, 775217, tzinfo=<UTC>)

# value 변경 후 저장 
>>> q.question_text = "What's up?"
>>> q.save()

# 이제는 객체 1개 나옴
>>> Question.objects.all() 
<QuerySet [<Question: Question object (1)>]>

객체 표현에 변화를 주기 위해,
__str__() 메소드 추가 > django가 자동으로 생성하는 관리사이트에서도 객체의 표현이 사용됨

# polls/models.py


from django.db import models

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

class Choice(models.Model):
    # ...
    def __str__(self):
        return self.choice_text

모델에 timezone도 추가

# polls/models.py


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)

다시 Shell을 열고

>>> from polls.models import Choice, Question

>>> Question.objects.all()
<QuerySet [<Question: What's up?>]>    # 추가된 __str__() 확인

# filter: database lookup API
>>> Question.objects.filter(id=1)
<QuerySet [<Question: What's up?>]>
>>> Question.objects.filter(question_text__startswith='What')
<QuerySet [<Question: What's up?>]>

# get (올해 publish된 객체 가져오기)
>>> from django.utils import timezone
>>> current_year = timezone.now().year
>>> Question.objects.get(pub_date__year=current_year)
<Question: What's up?>

# 요청한 조건에 만족하는 객체가 없을 경우, exception 발생
>>> Question.objects.get(id=2)
Traceback (most recent call last):
    ...
DoesNotExist: Question matching query does not exist.

# primary key
>>> Question.objects.get(pk=1)
<Question: What's up?>

# was_published_recently()
>>> q = Question.objects.get(pk=1)
>>> q.was_published_recently()    # 24시간 내에 publish된 것인가
True



# ForeignKey 참조하기
>>> q = Question.objects.get(pk=1)

# 자신(Question)을 참조하는 모델이 'lowercase_set'의 형태로 접근한다. > choice_set
# choice 객체의 개수를 묻는 것
>>> q.choice_set.all()
<QuerySet []>    # 아직 없다.

# 3개의 choices 만들기
>>> q.choice_set.create(choice_text='Not much', votes=0)
<Choice: Not much>
>>> q.choice_set.create(choice_text='The sky', votes=0)
<Choice: The sky>

>>> c = q.choice_set.create(choice_text='Just hacking again', votes=0)

# c가 참조한 question object 보여주기 
>>> c.question
<Question: What's up?>

# choice 객체 불러오기
>>> q.choice_set.all()
<QuerySet [<Choice: Not much>, <Choice: The sky>, <Choice: Just hacking again>]>
>>> q.choice_set.count()
3



# 올해 publish된 Choice 가져오기 (관계를 구분하기위해 '__')
# current_year = timezone.now().year
>>> Choice.objects.filter(question__pub_date__year=current_year)
<QuerySet [<Choice: Not much>, <Choice: The sky>, <Choice: Just hacking again>]>


# 객체 지우기
>>> c = q.choice_set.filter(choice_text__startswith='Just hacking')
>>> c.delete()

Field lookups (__: double-underscore)


관리자 생성하기

# 관리자 생성
$ python manage.py createsuperuser

# 관리자 계정 만들기
Username: admin
Email address: admin@example.com
Password: **********
Password (again): *********
Superuser created successfully.

# 서버 켜고 'http://127.0.0.1:8000/admin/' 접속
$ python manage.py runserver

관리자 사이트

아래 보이는 컨텐츠들은 django.contrib.auth 모듈에서 제공

poll app을 관리 인덱스 페이지에 띄우려면,

# polls/admin.py


from django.contrib import admin
from .models import Question

admin.site.register(Question)
profile
Hello World!

0개의 댓글

관련 채용 정보