221008_점프투장고 2-01 ~ 2-03

Csw·2022년 10월 8일
0

Django

목록 보기
9/14

🌉 점프 투 장고 사이트를 참고하여 일정 단위의 chapter에 대해 실습 후 새롭게 알게된 내용, 혹은 복습이 꼭 필요한 내용에 대해 정리!!

🌞 2-01. URL과 View


🌈 장고 개발 흐름 정리하기

[1] 브라우저에서 로컬 서버로 http://localhost:8000/pybo 페이지를 요청
[2] urls.py 파일에서 /pybo URL 매핑을 확인하여 views.py 파일의 index 함수를 호출
[3] 호출한 결과를 브라우저에 반영


🌈 URL 분리

pybo 앱에 관련한 것들은 pybo 앱 디렉터리 하위에 위치해야 함.

  • config의 urls.py 파일은 앱이 아닌 프로젝트 성격의 파일이므로, 이곳에는 프로젝트 성격의 URL 매핑만 추가되어야 함.
  • 따라서 pybo 앱에서만 사용하는 URL 매핑을 pybo/urls.py 파일로 분리하여 관리할 것!

📄 /config/urls.py

from django.contrib import admin
from django.urls import path, include
# from pybo import views  → 더 이상 필요하지 않으므로 삭제

urlpatterns = [
    path('admin/', admin.site.urls),
    path('pybo/', include('pybo.urls')),  # ← 추가한 코드
]

path('pybo/', include('pybo.urls'))

  • pybo/로 시작하는 페이지를 요청하면 이제 pybo/urls.py 파일의 매핑 정보를 읽어서 처리하라는 의미
  • 따라서 이제 pybo/로 시작하는 URL (예시 : pybo/question/create, pybo/answer/create)을 추가해야 할 때 config/urls.py 파일을 수정할 필요없이 pybo/urls.py 파일만 수정하면 됨.

📄 /pybo/urls.py

from django.urls import path

from pybo.views import index

urlpatterns = [
    path('', index),
]
  • 기존 /config/urls.py 파일에 설정했던 내용과 별반 차이가 없음.
  • 다만 path('', index) 처럼 pybo/ 가 생략된 '' 이 사용됨.
    • 이렇게 되는 이유는 config/urls.py 파일에서 이미 pybo/로 시작하는 URLpybo/urls.py 파일과 먼저 매핑되었기 때문.
  • 즉, pybo/ URL은 다음처럼 config/urls.py 파일에 매핑된 pybo/pybo/urls.py 파일에 매핑된 '' 이 더해져 pybo/가 됨.


🌞 2-02. Model


🌈 ORM

🚦 쿼리문

데이터베이스의 데이터를 생성, 조회, 수정, 삭제하기 위해 사용하는 질의문(문법)

🚦 ORM

  1. 전통적으로 데이터베이스를 사용하는 프로그램들은 데이터베이스의 데이터를 조회하거나 저장하기 위해 쿼리문을 사용해야 했다.
  2. 이 방식은 여전히 많이 사용되고 있는 방식이지만 몇 가지 단점이 있다.
    • 개발자마다 다양한 쿼리문이 만들어지고, 또 잘못 작성된 쿼리는 시스템의 성능을 저하 시킬수 있기 때문이다.
    • 그리고 데이터베이스를 MySQL에서 오라클로 변경하면 프로그램에서 사용한 쿼리문을 모두 해당 데이터베이스의 규칙에 맞게 수정해야 하는 어려움도 생긴다.
  • ORM(Object Relational Mapping)을 사용하면 데이터베이스의 테이블을 모델화하여 사용하기 때문에 위에서 열거한 SQL방식의 단점이 모두 없어짐.
  • ORM을 사용하면 개발자별로 독특한 쿼리문이 만들어질 수가 없고 또 쿼리를 잘못 작성할 가능성도 낮아짐.
  • 그리고 데이터베이스 종류가 변경되더라도 쿼리문이 아닌 모델을 사용하기 때문에 프로그램을 수정할 필요가 없음.

🌈 CASCADE 옵션

🚦 ForeignKey

  • Answer 모델은 질문에 대한 답변에 해당되므로 Question 모델을 속성으로 가져가야함.
  • 기존 모델을 속성으로 연결하려면 ForeignKey를 사용해야 함.
  • ForeignKey는 다른 모델과 연결하기 위해 사용.

🚦 on_delete=models.CASCADE

  • 이 답변(Answer)과 연결된 질문(Question)이 삭제될 경우 답변(Answer)도 함께 삭제된다는 의미

  • 질문 하나에는 무수히 많은 답변이 등록될 수 있음.

  • CASCADE 옵션은 질문을 삭제하면 그에 달린 답변들도 모두 함께 삭제

  • 장고에서 사용하는 속성(Field)의 타입은 이것 외에도 많음.


🌈 sqlmigrate

  • makemigrations로 데이터베이스 작업 파일을 생성하고 migrate 명령을 실행하기 전에 실제 어떤 쿼리문이 실행되는지 sqlmigrate 명령으로 확인해 볼 수 있음.
  • sqlmigrate 명령은 단지 실행되는 쿼리만 조회할 뿐이며, 실제 쿼리가 수행되지는 않음.

📌 다음의 명령어를 Terminal 창에서 실행

python manage.py sqlmigrate '앱이름' 'makemigrations으로 생성된 파일 이름'

  • 예시
(mysite) c:\projects\mysite> python manage.py sqlmigrate pybo 0001
BEGIN;
--
-- Create model Question
--
CREATE TABLE "pybo_question" ("id" integer NOT NULL PRIMARY KEY AUTOINCREMENT, "subject" varchar(200) NOT NULL, "content" text NOT NULL, "create_date" datetime NOT NULL);
--
-- Create model Answer
--
CREATE TABLE "pybo_answer" ("id" integer NOT NULL PRIMARY KEY AUTOINCREMENT, "content" text NOT NULL, "create_date" datetime NOT NULL, "question_id" bigint NOT NULL REFERENCES "pybo_question" ("id") DEFERRABLE INITIALLY DEFERRED);
CREATE INDEX "pybo_answer_question_id_e174c39f" ON "pybo_answer" ("question_id");
COMMIT;

(mysite) c:\projects\mysite>
  • python manage.py sqlmigrate pybo 0001명령에서 pybo는 앱 이름을 의미하고 0001은 생성된 작업파일(예: 0001_initial.py)의 일련번호를 의미.
  • SQL 문에 익숙한 독자라면 데이터베이스에 어떤 일들이 벌어질지 유추할 수 있을 것이지만, 여기에 출력되는 SQL 문들이 무엇인지 몰라도 상관없음.
  • 장고는 이러한 SQL 대신 Model을 사용하기 때문

🌈 Django shell

장고 셸을 실행하여 모델을 사용하는 방법
장고 셸은 장고에 필요한 환경들이 자동으로 설정되어 실행됨.

📌 다음의 명령어를 Terminal 창에서 실행

python manage.py shell

🚦 Question 생성

  • Question과 Answer 모델은 장고 셸에서 다음처럼 import하여 사용할 수 있음.
>>> from pybo.models import Question, Answer
  • Question 모델을 이용하여 질문 데이터를 만들기
    • Question 모델의 create_date 속성은 DateTimeField 타입이므로 timezone.now()로 현재일시를 대입.
  • 아래처럼 Question 모델의 객체 q를 생성한 후 save함수를 실행하면 질문 데이터가 1건 생성됨.
>>> from django.utils import timezone
>>> q = Question(subject='pybo가 무엇인가요?', content='pybo에 대해서 알고 싶습니다.', create_date=timezone.now())
>>> q.save()
  • 데이터가 1건 생성되면 반드시 다음처럼 id 값이 생성됨.
>>> q.id
1
  • id는 모델 데이터의 유일한 값으로 프라이머리 키(PK:Primary Key)라고도 함.
  • 이 id 값은 데이터를 생성할 때마다 1씩 증가됨.
>>> q = Question(subject='장고 모델 질문입니다.', content='id는 자동으로 생성되나요?', create_date=timezone.now())
>>> q.save()
>>> q.id
2
1

🚦 Question 조회 : 전체 데이터 조회

  • 저장한 데이터를 조회
>>> Question.objects.all()
<QuerySet [<Question: Question object (1)>, <Question: Question object (2)>]>
  • 저장한 Question 모델의 데이터는 Question.objects 를 통해서 조회할 수 있음.

    • Question.objects.all()은 모든 Question 데이터를 조회하는 함수임.
    • 결과값으로는 QuerySet 객체가 리턴되는데 위처럼 Question 객체를 포함하고 있음.
    • Question object (1), Question object (2) 에서 1과 2는 Question 데이터의 id 값을 의미.
  • 다음처럼 Question 모델에 str 메서드를 추가하면 id 값 대신 제목을 표시할 수 있음.

📄 /pybo/urls.py

(... 생략 ...)

class Question(models.Model):
    subject = models.CharField(max_length=200)
    content = models.TextField()
    create_date = models.DateTimeField()

    def __str__(self):          # 추가한 코드
        return self.subject     # 추가한 코드

(... 생략 ...)
  • 모델이 변경되었으므로 장고 셸을 재시작해야 변경된 결과를 확인할 수 있음.

    장고 셸을 종료하기 위해서는 장고 셸에서 Ctrl+Z 또는 quit()을 입력.

  • 이렇게 수정하고 Question.objects.all() 함수를 다시 실행
(mysite) c:\projects\mysite>python manage.py shell
>>> from pybo.models import Question, Answer
>>> Question.objects.all()
<QuerySet [<Question: pybo가 무엇인가요?>, <Question: 장고 모델 질문입니다.>]>
>>>
  • 1과 2라는 id 값 대신 이제 제목이 표시되는 것을 확인 가능.

❗❗ 모델에 메서드가 추가될 경우에는 makemigrations와 migrate를 수행할 필요가 없음.

  • makemigrations, migrate 명령이 필요한 경우는 모델의 속성이 변경되었을때 뿐이다.

🚦 특정 데이터 조회 : filterget

  • 이번에는 filter를 사용하여 id 값이 1인 Quesiton 데이터를 조회.
    • filter는 조건에 해당되는 데이터를 모두 리턴해 주기 때문에 다건을 의미하는 QuerySet이 리턴됨.
>>> Question.objects.filter(id=1)
<QuerySet [<Question: pybo가 무엇인가요?>]>
  • id는 유일한 값이므로 filter 대신 get을 이용하여 조회할 수도 있다.
    • get으로 조회할 경우 QuerySet이 아닌 Question 모델 객체가 리턴됨.
    • filter는 다건을 리턴하지만 get은 한 건만 리턴하기 때문.
    • 하지만 get으로 조회시 조건에 맞는 데이터가 없으면 오류가 발생
      • get은 반드시 1건의 데이터를 조회할 때 사용함.
      • 보통 get은 id와 같은 유일한 값으로 조회할 경우에만 사용.
Code>
>>> Question.objects.get(id=1)
<Question: pybo가 무엇인가요?>

🚦 특정 문자열을 포함한 조회 : __contains

  • 이번에는 subject에 "장고"라는 문자열이 포함된 데이터만 조회
    • subject__contains='장고'의 의미는 "subject에 '장고'라는 문자열이 포함되어 있는가?" 라고 해석할 수 있다. subject__contains 에서 언더바(_)가 1개가 아닌 2개임에 주의하자.
>>> Question.objects.filter(subject__contains='장고')
<QuerySet [<Question: 장고 모델 질문입니다.>]>

📌 데이터를 조회하는 filter의 사용법은 위에서 알아본 것 외에도 아주 많음.


🚦 Question 수정

  • id 값이 2인 Question 데이터를 조회
>>> q = Question.objects.get(id=2)
>>> q
<Question: 장고 모델 질문입니다.>
  • subject 속성을 다음과 같이 수정
>>> q.subject = 'Django Model Question'
>>>
  • 여기까지만 해서는 수정이 되지 않음.
    • 다음처럼 save를 수행해 주어야 변경된 데이터가 반영된다는 점을 꼭 기억할 것!!
>>> q.save()
>>> q
<Question: Django Model Question>

🚦 Question 삭제

  • id 값이 1인 Question 데이터를 삭제
>>> q = Question.objects.get(id=1)
>>> q.delete()
(1, {'pybo.Question': 1})
  • 실제로 삭제되었는지 다음처럼 Question.objects.all() 로 확인
>>> Question.objects.all()
<QuerySet [<Question: Django Model Question>]>

🚦 Answer 작성

  • 답변 데이터를 생성
>>> q = Question.objects.get(id=2)
>>> q
<Question: Django Model Question>
>>> from django.utils import timezone
>>> a = Answer(question=q, content='네 자동으로 생성됩니다.', create_date=timezone.now())
>>> a.save()
  • 답변 데이터를 만들기 위해서는 질문이 필요하므로 id가 2인 질문을 먼저 조회한 후 question 속성에 대입.
  • Answer 모델도 Question 모델과 마찬가지로 유일한 값을 의미하는 id가 자동으로 생성됨.
>>> a.id
1

🚦 Answer 조회

  • 답변을 조회하는 방법은 질문과 마찬가지로 Answer의 id 값을 사용
>>> a = Answer.objects.get(id=1)
>>> a
<Answer: Answer object (1)>
  • Answer 객체인 a를 사용하면 답변에 연결된 질문도 조회 가능
>>> a.question
<Question: Django Model Question>

❗❗ Answer 모델 객체인 a를 통해서 질문을 찾는것은 Answer 모델에 question 속성이 연결되어 있기 때문에 매우 쉬움.

  • 그렇다면 질문을 이용하여 답변을 찾는 것은 가능?

    Yes

    • q.answer_set을 사용하면 질문에 연결된 답변을 가져올 수 있음.
    • Question 모델에는 answer_set 이라는 속성이 없지만 Answer 모델에 Question 모델이 ForignKey로 연결되어 있기 때문에 q.answer_set 과 같은 역방향 접근이 가능
>>> q.answer_set.all()
<QuerySet [<Answer: Answer object (1)>]>

📌 연결모델명_set 방법

  • 연결모델명_set(예:answer_set)은 상식적으로 생각하면 더 쉬움.
    • 질문 하나에는 여러개의 답변이 가능하므로 q.answer_set이 가능하지만 답변 하나에는 여러개의 질문이 있을 수 없으므로 a.question_set은 불가능.
    • 답변 하나에는 질문 하나만 가능하기 때문에 a.question만 가능.

🌞 2-03. Django Admin


🌈 모델 관리

  • 이미 생성한 Question 모델을 Admin에 등록하는 방법

📄 /pybo/admin.py

from django.contrib import admin
from .models import Question         # 추가한 코드

admin.site.register(Question)        # 추가한 코드


🌈 모델 검색

  • 관리자 화면에서 제목(subject)으로 질문 데이터를 검색하기 위해 Search 기능 추가
    • 다음처럼 pybo/admin.py 파일을 수정
      • Question 모델에 세부 기능을 추가할 수 있는 QuestionAdmin 클래스를 생성
      • 제목 검색을 위해 search_fields 속성에 'subject'를 추가

📄 /pybo/admin.py

from django.contrib import admin
from .models import Question


class QuestionAdmin(admin.ModelAdmin):          # 추가한 코드 
    search_fields = ['subject']                 # 추가한 코드 


admin.site.register(Question, QuestionAdmin)    # 추가한 코드 
  • 이렇게 수정하면 다음처럼 검색기능이 추가된 화면 확인 가능.

  • 아래 두 가지 방식은 동일
    • 2번째 방식은 김형종 강사님 수업 시간에 배운 방식

❗❗ 장고 관리자에는 이 외에도 무수히 많은 기능들이 있음.

0개의 댓글