Back-end/Django

Django 기본 요소 (URL과 View, Model)

김병찬 2024. 12. 29. 16:22

앞선 포스팅에서 "mysite" 라는 Project를 생성하였음.

https://devidas.tistory.com/55

App

  • 프로젝트 단독으로는 아무런 일도 할 수 없으므로 기능을 추가하기 위해서는 App을 만들어야 함
  • 게시판 기능을 담당할 pybo 앱 생성
(mysite) C:/projects/mysite > django-admin startapp pybo

 

 

  • migrations : Directory로 Django가 DB Table을 생성하고 수정하기 위한 파일들을 이곳에서 관리함.
  • admin.py : Django 관리자 화면을 구성하는 파일이다. 이 곳에 코드를 추가하여 Django 관리자 화면을 제어할 수 있음
  • apps.py : App의 구성 정보를 정의하는 파일
  • models.py : DB Model 정의하는 파일
  • tests.py : App을 테스트할 때 사용하는 파일
  • views.py : App의 기능을 구현하는 파일로, 앞으로 가장 많이 사용할 파일

Hello Pybo

(mysite) C:\projects\mysite> python manage.py runserver # Local server 구동

 

  • 단지 http://127.0.0.1:8000/pybo page를 요청하면 다음과 같이 404 HTTP 오류 코드가 뜬다

 

  • 404 오류는 브라우저가 요청한 페이지를 찾을 수 없을 경우에 발생함
  • Django 는 실행 중 오류가 발생하면 화면에 원인을 자세히 표시해 주어 파악이 쉬운데 이 경우 오류 내용은 config.urls 에 pybo/ URL에 대한 Mapping이 없다는 것
  • config.urls Module : config/urls.py file을 의미함
  • Django urls.py file은 페이지 요청이 발생하면 가장 먼저 호출되는 파일로 URL과 View function을 연결하는 역할
  • view function : views.py 파일에 정의된 함수

urls.py

from django.contrib import admin
from django.urls import path

from pybo import views

urlpatterns = [
	path('admin/', admin.site.urls),
    path('pybo/', views.index), # pybo/ URL이 요청되면 views.index 호출
]
# views.index : views.py 파일의 index 함수

 

urlpatterns & path
urlpatterns : Django 에서 URL과 view function 간의 Mapping을 설정하는 데 사용되는 중요한 변수
path(URL 경로, 호출할 view function) : URL과 view를 Mapping 하는 Django function

 

  • 실제 URL과는 다르게 host name과 port가 생략된 'pybo/' 로 Mapping 해야 하는데 서버가 어떤 환경에서 실행되는지에 따라 변하기 때문임
  • pybo 뒤에 /(슬래시) 를 붙인 이유는 브라우저에서 슬래시를 빼고 입력해도 자동으로 넣어서 변환되기 때문이다. 이 이유는 Django의 URL 정규화 기능 덕분인데 특별한 경우가 아니라면 URL Mapping 시 항상 끝에 / (슬래시)를 붙이는 것이 좋음

views.py

  • HttpResponse : 요청에 대한 응답을 할 때 사용
  • index 함수의 매개변수 request는 HTTP 요청 객체
from django.http import HttpResponse

def index(request):
	return HttpResponse("안녕하세요 pybo에 오신 것을 환영합니다.")

 

Django 개발 흐름 정리

 

 

  • [1] : Browser 에서 Local Server 로 "http://127.0.0.1:8000/pybo" Page를 요청
  • [2] : urls.py file 에서 "/pybo" URL Mapping을 확인하여 views.py file의 index 함수를 호출
  • [3] : 호출한 결과를 Browser에 반영

URL 분리

  • "config/urls.py" 는 Project 전반적인 URL을 관리하는 파일로, App 별 URL Mapping은 여기 포함되지 않는 것이 좋음
  • URL 분리를 통해 Project 구조를 정리하고, 각 앱이 독립적으로 동작할 수 있도록 유지 보수성을 높일 수 있음.
# config/urls.py

from django.contrib import admin
from django.urls import path, include

urlpatterns = [
	path('admin/', admin.site.urls),
    # "pybo/" 로 시작하는 페이지를 요청하면 "pybo/urls.py" 파일의 Mapping 정보를 읽어서 처리하라는 의미
    # "pybo/"로 시작하는 URL을 추가해야 할 때 "config/urls.py" 파일을 수정할 필요 없이 "pybo/urls.py" 파일만 수정하면 됨
    path('pybo/', include('pybo.urls'), 
]

 

 

  • "path('', views.index)" 처럼 "pybo/"가 생략된 이유는 "config/urls.py" 파일에서 이미 "pybo/"로 시작하는 URL이 "pybo/urls.py" 파일과 먼저 Mapping 되었기 때문임.
config/urls.py   pybo/urls.py   최종 URL
'pybo/' + '' = 'pybo/'
'pybo/' + 'question/create/' = 'pybo/question/create/'
# pybo/urls.py
from django.urls import path

from . import views

urlpatterns = [
	path('', views.index), 
]

 

Model

  • Django 는 Model 을 이용하여 DB를 처리함
  • SQL Query 문 없이 데이터를 쉽게 처리할 수 있음

1️⃣ Django App migrate

  • 18개의 적용되지 않은 migration 존재한다는 문구
  • admin, auth, contenttypes, sessions app (Django Project를 생성할 때 기본적으로 설치되는 App)과 관련된 내용으로, 이를 적용하려면 "python manage.py migrate" 명령어를 실행해야 한다고 나와있음

 

  • settings.py 파일에서 설치된 App을 확인할 수 있는데, messages 와 staticfiles app이 있지만, DB와 관련이 없는 App이기 때문에 경고문에 포함되지 않음

  • DB engine 은 "django.db.backend.sqlite3" 로 정의되어 있는데, DB 파일은 BASE_DIR Directory 아래의 "db.sqlite3" 파일에 저장되도록 설정되어 있음. (여기서 말하는 BASE_DIR : Proejct Directory)
SQLite 란

SQLite는 주로 개발용이나 소규모 프로젝트에서 사용되는 가벼운 파일 기반 데이터베이스이다.
개발 단계에서는 SQLIte를 사용해 빠르게 개발하고, 실제 운영 시스템에서는 더 규모 있는 데이터베이스를 사용하는 것이 일반적인 개발 패턴이다.

 

  • "python manage.py migrate" 명령을 실행하여 해당 App 들이 필요로 하는 DB Table 생성
(mysite) (base) b._.chan@gimbyeongchan-ui-MacBookAir mysite % python manage.py migrate

 

 

2️⃣ DB Browser for SQLite

 

  • Django 의 큰 장점 중 하나는 Table 작업을 위해 직접 Query 문을 작성하거나 실행할 필요가 없다는 점 (ORM 사용)
ORM (Object Relational Mapping)

DB 를 변경할 경우 프로그램에서 작성한 Query 문을 해당 DB 규칙에 맞게 수정해야 하는 어려움이 존재한다.
ORM 을 사용하면 DB Table 을 객체 모델로 추상화하여 사용할 수 있어, SQL 방식의 단점이 모두 해소됨.
개발자별로 독특한 Query 문이 작성될 여지가 없으며, Query를 잘못 작성할 가능성도 낮아짐.
DB 종류가 변경되더라도 Query 문이 아닌 Model 을 기반으로 동작하기 때문에 프로그램을 수정할 필요가 없음.

 

3️⃣ Model 작성하기

  • 이번에 만들 pybo 는 질문과 답변을 주고받을 수 있는 Python 게시판 Service
  • 질문과 답변을 위한 Data Model 이 필요함

❶ 모델의 속성

[Question Model]

속성 설명
subject 질문의 제목
content 질문의 내용
create_date 질문을 작성한 일시

 

[Answer Model]

속성 설명
question 질문 (어떤 질문의 답변인지 알아야 하므로 질문 속성 필요)
content 답변의 내용
create_date 답변을 작성한 일시

 

 

❷ models.py

# models.py

from django.db import models

class Question(models.Model):
	subject = models.CharField(max_length=200) # 최대 200자, 제목처럼 글자 수가 제한된 텍스트는 CharField 사용
    content = models.TextFIeld() # 내용처럼 글자 수에 제한이 없는 텍스트는 TextField 사용
    create_date = models.DateTimeField() # 날짜와 시간 정보를 저장하는 속성은 DateTimeField 사용
    
class Answer(models.Model):
	question = models.ForeignKey(Question, on_delete=models.CASCADE)
    # 기존 모델을 속성으로 연결하기 위해 ForeignKey 사용
    # 두 모델 간의 관계를 정의할 때 사용되며 on_delete=models.CASCADE : 답변이 연결된 질문이 삭제되면 해당 답변도 함께 삭제
    content = models.TextField()
    create_date = models.DateTimeField()

 

 

Model field reference | Django documentation

The web framework for perfectionists with deadlines.

docs.djangoproject.com

 

❸ Table 생성

  • Table 을 생성하려면 pybo App 을 "config/settings.py" 파일의 "INSTALLED_APPS" 항목에 추가하여야 함

 

  • 'pybo.apps.PyboConfig' class 는 "pybo/apps.py" 파일에 정의된 클래스로, pybo app을 생성할 때 자동으로 만들어지며 별도로 작성할 필요가 없음.

 

❹ makemigrations

  • 모델이 새로 생성되거나 변경된 경우 "makemigrations"  명령을 먼저 실행하여 migration file을 먼저 생성한 뒤, 그 파일을 기반으로 "migrate" 명령을 수행해야 한다.

 

  • "makemigrations" : 모델을 생성하거나 모델에 변경 사항이 있을 경우 실행해야 하는 명령으로, "pybo\migrations\0001_initial.py" 라는 Migration file 이 자동으로 생성됨

  • 한 번 더 실행해도 변경 사항이 없음을 알려주기 때문에 문제가 발생하지 않음
  • "makemigrations" 명령을 수행하더라도 실제로 테이블이 생성되지는 않고 Django 가 테이블 작업을 수행하기 위한 작업 파일을 생성하는 데 사용됨
  • 실제 테이블 생성 작업은 "migrate" 명령을 통해서만 이루어짐

 

❺ sqlmigrate

  • "makemigrations" 로 DB File을 생성한 후, "migrate" 명령을 실행하기 전에 실제 어떤 Query 문이 실행될지 "sqlmigrate" 명령을 통해 확인할 수 있음
  • "sqlmigrate" 명령은 실행될 Query를 단순히 조회할 뿐이며, 실제로 Query가 수행되지는 않음

 

  • "python manage.py sqlmigrate pybo 0001" 명령에서 "pybo"는 App Name, "0001" 은 생성된 작업 파일(ex : 0001_initial.py)의 일련번호

❻ migrate

  • 실제 테이블은 위 사진처럼 생성되었지만 실제 코딩할 때는 알 필요 없는데, "Question", "Answer" 같은 Model 을 사용하기 때문임.

4️⃣ Model 사용하기

  • 일반적인 python sell이 아닌 "python manage.py shell" 명령으로 Django Shell 을 실행해야 한다.
  • Django 에 필요한 환경이 자동으로 설정된 상태에서 실행되므로 Model 이나 설정 등을 바로 사용할 수 있음

❶ Question 생성

  • Question, Answer Model 은 Django Shell 에서 import 해서 사용 가능
  • Question model을 사용하여 질문 데이터 생성
  • create_date 속성은 "DateTimeField" 타입이므로 "timezone.now() 를 사용하여 현재 일시 대입
  • Question model 의 객체 q를 생성한 후 save() method 를 실행하면, DB에 질문 데이터가 1건 저장됨
  • 데이터가 1건 생성되면 반드시 "id" 값이 자동으로 생성되는데, 이 값은 모델 데이터의 고유한 값으로 PK(Primary Key) 라고 함.
  • 데이터를 생성할 때마다 자동으로 증가하며, DB 에서 각 Record 를 고유하게 식별하는 데 사용됨

 

❷ Question 조회

 

  • 저장한 Question Model 의 데이터는 "Question.objects" 를 통해 조회할 수 있음
  • "Question.objects.all()" 결과값으로 QuerySet 객체를 반환하며, 그 안에는 저장된 Question 객체들이 포함되어 있음.
  • "Question object (1) 과 (2)" 는 각각 id 값이 1과 2인 Question 데이터 객체를 나타냄'
# models.py

(... 생략 ...)

class Question(models.Model):
	subject = models.CharField(max_length=200)
    content = models.TextField()
    create_date = models.DateTimeField()
    
    # id 값 대신 제목을 표시할 수 있음
    def __str__(self):
    	return self.subject

(... 생략 ...)

 

  • Django Shell 을 종료하기 위해서는 Shell 에서 Ctrl + Z or quit() 입력하면 됨
  • Model 에 method 가 추가될 경우 "makemigrations" 와 "migrate" 를 수행할 필요가 없음
  • 필드가 추가되거나 삭제되거나 변경된 경우에만 필요한 것

  • filter 는 조건에 해당하는 데이터를 모두 Return 해주기 때문에 결과는 다건을 의미하는 "QuerySet" 객체가 Return

 

  • get 으로 조회할 경우 Question Model 객체가 Return 됨. (한건만!)
  • 조건에 맞는 데이터가 없으면 오류가 발생

 

 

Making queries | Django documentation

The web framework for perfectionists with deadlines.

docs.djangoproject.com

 

❸ Question 수정

  • 반드시 "save()"를 수행해 주어야 변경된 데이터가 반영된다는 것을 기억

❹ Question 삭제

 

  • "delete"를 수행하면 해당 데이터가 삭제됨
  • 삭제될 때는 추가 정보가 Return 됨

❺ Answer 작성

  • Answer Model 도 Question Model과 마찬가지로 유일한 값을 의미하는 id가 자동으로 생성됨

❻ Answer 조회

  • 답변을 조회하는 방법은 Answer의 id 값을 사용하면 됨.
  • Answer 객체인 a를 사용하면 답변에 연결된 질문도 조회 가능
  • Answer Model 에 "question" 속성이 연결되어 있기 때문에 가능.
  • "q.answer_set" 을 사용하면 질문에 연결된 답변을 가져올 수 있음
  • Answer Model 에 Question Model 이 ForeignKey 로 연결되어 있기 때문에 q.answer_set 과 같은 역방향 접근 가능
  • 연결모델명_set 방법은 자주 사용하니 꼭 기억!!