질문목록, 질문상세 기능 구현

pybo에 핵심 기능인 질문 목록과 질문 상세 기능을 구현하자.

질문 목록 : 질문들을 게시물 목록으로 조회

질문 상세 : 한 건의 데이터를 상세히 조회

admin에서 쉽게 구현했던 기능들을, pybo에 구현해 보자.

질문 목록

질문 목록이 출력되도록 pybo\views.py 파일 수정

[파일명: C:\projects\yoursite\pybo\views.py] 아래 코드로 전체를 대체

from django.shortcuts import render
from .models import Question


def index(request):
    """
    pybo 목록 출력
    """
    question_list = Question.objects.order_by('-create_date')
    context = {'question_list': question_list}
    return render(request, 'pybo/question_list.html', context)

Question.objects 로 질문 목록 데이터를 가져옴

order_by 는 조회 결과를 정렬하는 함수. '-create_date'는 작성일시 역순 정렬의미. -없으면 순방향.

context는 [C:\projects\yoursite\config\settings.py]의 TEMPLATES에 context값으로 반환해줌.

render 함수는 파이썬데이터를 템플릿에 적용하여 HTML로 반환하는 함수.question_list 데이터를 pybo/question_list.html(템플릿) 파일에 적용하여 HTML을 리턴한다.

템플릿 디렉터리

render 함수에서 사용한 템플릿(pybo/question_list.html) 파일을 작성해야 한다.템플릿을 저장할 디렉터리는 config/settings.py 에 추가(등록)해줘야 한다.

[파일명 : C:\projects\yoursite\config\settings.py] #수정

 

(생략)
TEMPLATES = [
    {
        'BACKEND': 'django.template.backends.django.DjangoTemplates',
        'DIRS': [#BASE_DIR / 'templates'],
        'APP_DIRS': True,
        'OPTIONS': {
            'context_processors': [
                'django.template.context_processors.debug',
(생략)

BASE_DIR은 c:\projects\mysite 이므로 디렉터리를 만들자

(yoursite) C:\projects\yoursite>mkdir templates

템플릿들은 앱 디렉토리에서 관리하지 않고, 템플릿 디렉터리에서 관리하자.

(yoursite) C:\projects\yoursite\templates>mkdir pybo

pybo/question_list.html 파일을 만들고, 작성하자

[파일명 : C:\projects\yoursite\templates\pybo\question_list.html] 아래 코드로 작성

{% if question_list %}
    <ul>
    {% for question in question_list %}
        <li><a href="/pybo/{{ question.id }}/">{{ question.subject }}</a></li>
    {% endfor %}
    </ul>
{% else %}
    <p>질문이 없습니다.</p>
{% endif %}

{% if question_list %}

question_list가 있다면 (question_list는 render 함수로 전달받은 "질문 목록" 데이터이다.)

{% for question in question_list %}

question_list 에서 하나씩 question 에 대입

{{ question.id }}

for문에 의해 대입된 question 객체의 id번호 출력

{{ question.subject }}

for문에 의해 대입된 question 객체의 제목 출력

Django 템플릿 언어

템플릿과 언어를 더 알고 싶다면 이 링크 클릭

 

Templates | Django documentation | Django

Django The web framework for perfectionists with deadlines. Overview Download Documentation News Community Code Issues About ♥ Donate

docs.djangoproject.com

테스트

질문 목록 기능 완성

질문 상세

'왜이러지?' 질문을 클릭하면

http://127.0.0.1:8000/pybo/2/의 URL을 가지고 있다.

URL이 동작할 수 있도록 pybo/urls.py 파일에서 매핑을 해주자.

[파일명: C:\projects\yoursite\pybo\urls.py] #라인 추가

from django.urls import path

from . import views

urlpatterns = [
    path('', views.index),
    #path('<int:question_id>/', views.detail)
]

문자로 저장되어있는 id를 int로 숫자로 바꿔주고 mapping하여 views.detail 함수를 실행함

views.detail

pybo/views.py 파일에 detail 함수를 추가하자

[파일명: C:\projects\yoursite\pybo\views.py] 아래 코드를 다 추가

(생략)
def detail(request, question_id):
    """
    pybo 내용 출력
    """
    question = Question.objects.get(id=question_id)
    context = {'question': question}
    return render(request, 'pybo/question_detail.html', context)

detail 함수 호출시 매개변수로 request 외에 question_id도 전달됨.

http://localhost:8000/pybo/2/ 페이지가 요청되면, detail함수에 request와 2가 전달됨.

question_detail.html

pybo/question_detail.html 템플릿을 만들자.

[파일명: C:\projects\yoursite\templates\pybo\question_detail.html] 아래 코드로 파일생성

<h1>{{ question.subject }}</h1>

<div>
    {{ question.content }}
</div>

{{ question.subject }} 와 {{ question.content }} 는 detail함수에서 context로 넘겨받은 데이터.

테스트

오류 페이지

http://localhost:8000/pybo/30/ 를 요청해보자

위의 경우 브라우저에 전달되는 오류코드가 500인데 404를 전달해야 바람직하다

오류코드 설명
200 성공
500 서버오류
404 서버가 요청한 페이지를 찾을 수 없음

404 페이지를 출력하도록 detail 함수 수정

[파일명: C:\projects\yoursite\pybo\views.py] #라인 수정

from django.shortcuts import render#, get_object_or_404
from .models import Question

(... 생략 ...)

def detail(request, question_id):
    """
    pybo 내용 출력
    """
    question = #get_object_or_404(Question, pk=question_id)
    context = {'question': question}
    return render(request, 'pybo/question_detail.html', context)

pk는 Primary Key인 id를 의미한다.

http://localhost:8000/pybo/30/

 

장고 제네릭뷰

다음에 따로 조사 후 포스팅 할 계획이다

장고 관리자(admin)

장고가 기본적으로 지원해주는 매우 편리한 기능이다.

슈퍼유저(superuser)

장고 관리자를 사용하기 위해, python manage.py createsuperuser를 명령해 장고 관리자 화면에 접속 가능한 슈퍼유저를 먼저 생성

(yoursite) C:\projects\yoursite>python manage.py createsuperuser
Username (leave blank to use 'pc'): admin
Email address: admin@yoursite.com
Password:
Password (again):
This password is too common.
Bypass password validation and create user anyway? [y/N]: y
Superuser created successfully.

Password line 은 입력해도 보안을 위해 ****와 같이, 블랭크로 표시된다.

나는 국방부의 슈퍼유저패스워드를 패스워드로 사용했다.

장고 관리자 화면

python manage.py runserver를 명령 해 서버를 구동시키고, 웹 브라우저로 http://localhost:8000/admin/ 에 접속.

모델 관리

한국어, 한국 서울시간으로 세팅을 바꿔 진행하겠다.

관리자에 Question, Answer 모델을 등록해보자

[파일명 : C:\projects\yoursite\pybo\admin.py] #라인 삽입

from django.contrib import admin
#from .models import Question, Answer

#admin.site.register(Question)
#admin.site.register(Answer)

관리자 페이지에서 모델을 사용할 수 있게 되었다.

관리자 검색 기능 추가

관리자 화면에서 제목(subject)으로 질문 검색 기능을 추가해보자.

[파일명: C:\projects\yoursite\pybo\admin.py] #수정

from django.contrib import admin
from .models import Question, Answer

#class QuestionAdmin(admin.ModelAdmin):
    #search_fields = ['subject']

admin.site.register(Question#, QuestionAdmin)
admin.site.register(Answer)

관리자에서 Question 제목 검색 기능을 구현시킬 QuestionAdmin 클래스 생성.

(admin.Modeladmin) 객체를 입력하면 해당 클래스는 기본으로 제공되는 기능이 아니라, 커스텀마이징 할 수 있음.

search_fields 속성에 subject 추가.

admin.site.register(Question)에 QuestionAdmin 객체를 전달하여 관리자 Questions 에 Question 과 QuestionAdmin 기능이 같이 추가됨. 

 

모델

장고는 모델(model)을 이용하여 데이터베이스(DB)를 처리한다. 모델을 사용하면 SQL 쿼리문 도움없이 데이터를 쉽게 처리할 수 있다.

pybo는 질문과 답변을 할 수 있는 파이썬 게시판 서비스이다.

질문과 답변에 해당하는 데이터 모델을 만들어 보자.

모델 속성

질문(Question) 모델에는 최소한 아래의 속성이 필요하다.

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

답변(Answer) 모델에는 최소한 아래의 속성이 필요하다

속성명 설명
question 질문
content 답변의 내용
create_date 답변을 작성한 일시

models.py

모델을 만들자

[파일명 : c\projects\yoursite\pybo\models.py] 내용 전체 대체

from django.db import models


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


class Answer(models.Model):
    question = models.ForeignKey(Question, on_delete=models.CASCADE)
    content = models.TextField()
    create_date = models.DateTimeField()

Question 모델

Quesetion 클래스를 통해 DB에 접속

제목은 최대 200자 까지 가능하도록 django.db 모듈의 models에서 CharField()를 통해 정의,

내용은 무제한 글자수의 텍스트로 만들기 위해 TextField()를 통해 정의,

작성일자는 날짜와 시간의 속성을 지닌 DataTimeField()를 통해 정의

__str__ 메서드 통해, 조회를 했을 때 id값 대신 제목이 표시되게 했다.

Answer 모델

Answer 클래스를 통해 DB에 접속

질문은 Question 모델의 속성을 가져야 하므로 ForeignKey()로 연결. Question과 연결하고, 연결된 질문(Question)이 삭제될 경우 답변(Answer)도 함꼐 삭제 된다는 의미

여러 속성의 Field 타입

https://docs.djangoproject.com/en/3.0/ref/models/fields/#field-types

pybo 앱 등록

작성한 모델을 사용하여 테이블을 생성해보자

테이블 : 데이터베이스에서 데이터를 저장하기 위한 데이터 집합의 모임. 데이터 표라 생각하자.

먼저 DB관련 작업을 수행하기 위해서, pybo앱을 config\settings.py에 등록하자

(생략)
INSTALLED_APPS = [
    #'pybo.apps.PyboConfig',
    'django.contrib.admin',
    'django.contrib.auth',
    (생략)
]
(생략)

migrate / makemigrations

python manage.py migrate를 통해 migrate를 시키면, 테이블이 생성된다.

(yoursite) C:\projects\yoursite>python manage.py migrate
Operations to perform:
  Apply all migrations: admin, auth, contenttypes, sessions
Running migrations:
  Applying contenttypes.0001_initial... OK
  Applying auth.0001_initial... OK
  Applying admin.0001_initial... OK
  Applying admin.0002_logentry_remove_auto_add... OK
  Applying admin.0003_logentry_add_action_flag_choices... OK
  Applying contenttypes.0002_remove_content_type_name... OK
  Applying auth.0002_alter_permission_name_max_length... OK
  Applying auth.0003_alter_user_email_max_length... OK
  Applying auth.0004_alter_user_username_opts... OK
  Applying auth.0005_alter_user_last_login_null... OK
  Applying auth.0006_require_contenttypes_0002... OK
  Applying auth.0007_alter_validators_add_error_messages... OK
  Applying auth.0008_alter_user_username_max_length... OK
  Applying auth.0009_alter_user_last_name_max_length... OK
  Applying auth.0010_alter_group_name_max_length... OK
  Applying auth.0011_update_proxy_permissions... OK
  Applying auth.0012_alter_user_first_name_max_length... OK
  Applying sessions.0001_initial... OK

모델이 신규로 생성되거나 변경되면 python manage.py makemigrations을 통해 makemigrations를 해야한다.

(yoursite) C:\projects\yoursite>python manage.py makemigrations
Migrations for 'pybo':
  pybo\migrations\0001_initial.py
    - Create model Question
    - Create model Answer

다시 모델이 업데이트된 테이블을 생성하자

(yoursite) C:\projects\yoursite>python manage.py migrate
Operations to perform:
  Apply all migrations: admin, auth, contenttypes, pybo, sessions
Running migrations:
  Applying pybo.0001_initial... OK

테이블 생성이 완료되었다.

이제 명령 프롬프트에서 모델의 클래스를 활용하여 DB를 이용할 수 있으나, 후에 UI를 통해 웹에서 동작을 확인할 것이므로 넘어가도록 하겠다. 또한 ORM(Object Relational Mapping)을 활용한 DB사용은 후에 정리에서 따로 포스팅할 예정이다.

수정한 라인은 # 으로 표시. 

1. 장고 개발 흐름

1) pybo(앱) 호출 -> 2) urls.py 에서 호출 -> 3) views.py 에서 기능 호출.

urls.py는 주소만 담고 있는 중간다리이며, 기능은 views.py 에 코딩되어있다.

 

앱(APP)

앱 생성

(yoursite) C:\projects\yoursite>django-admin startapp pybo

urls.py

[파일 이름 : c\projects\yoursite\config\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)
]

url 분리

pybo앱에 관련된 것은 pybo에서 관리하기 위해, url을 분리하여 관리해줄 것이다.

[파일이름 : c\projects\yoursite\config\urls.py] 수정

from django.contrib import admin
from django.urls import path#, include
#삭제

urlpatterns = [
    path('admin/', admin.site.urls),
    path('pybo/', #include('pybo.urls'))
]

path('pybo/', include('pybo.urls'))의 의미는 pybo/로 시작하는 페이지를 요청하면, pybo/urls.py 파일의 매핑 정보를 사용한다는 의미.

pybo 하위에 urls.py 파일 생성

[파일이름 : c\projects\yoursite\pybo\urls.py] 전부 해당 코드로 대체

from django.urls import path

from . import views

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

from . 은 현재 위치(c\projects\yoursite\pybo)를 가리킴.

path에 ''로 요청이 생략된 이유는 이미 config\urls.py로 부터 요청이 들어왔기 때문.

path로 http://127.0.0.1:8000/pybo/ 로 request 가 들어오면, pybo/views.py 의 index 함수에 request가 전달.

views 함수 추가

pybo/urls.py 로부터 views 함수들이 호출된다. index함수가 호출되었으니 간단히 응답의 하는 idex함수를 추가해보자.

[파일이름 : c\projects\yoursite\pybo\views.py] 전부 해당 코드로 대체

from django.http import HttpResponse


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

HttpResponse는 요청 페이지에 대한 응답을 하는 장고 클래스.

index 함수의 매개변수 request는 장고에 의해 자동으로 전달되는 HTTP 요청 객체라고한다.

즉, http://127.0.0.1:8000/pybo/ 를 통해 서버에 pybo를 호출 해달라는 요청(request)을 한다. 해당 request는 config\urls.py에서 pybo\urls.py 를 거쳐 pybo\views.py 의 index함수의 매개변수로 들어가 index함수를 호출하는 것이다.

앱 사용

(yoursite) C:\projects\yoursite>python manage.py runserver

를 통해 서버를 다시 시작하고 웹 브라우저에 http://127.0.0.1:8000/pybo/ 라는 request를 보내보자.

yoursite 프로젝트의 pybo 앱이 잘 작동하고 있는 것을 확인 할 수 있다.

가상환경 생성 및 3.1.3 버전의 장고 설치

C:\venvs> python -m venv yoursite
C:\venvs>cd C:\venvs\yoursite\Scripts
C:\venvs\yoursite\Scripts>activate
(yoursite) C:\venvs\yoursite\Scripts>
(yoursite) C:\venvs\yoursite\Scripts>pip install django==3.1.3

1. 프로젝트 생성

장고에는 프로젝트라는 개념이 있는데, 프로젝트 하나는 한 개의 웹사이트와 같다.

프로젝트에 여러 을 구성하여 웹사이트를 완성한다.

루트 디렉터리 생성 -> 장고 프로젝트 생성 -> 개발서버 구동

까지의 내용을 담고있다.

 

루트 디렉터리 생성

루트 디렉터리 projects 생성

C:\Users\PC>cd \
C:\>mkdir projects
C:\>cd projects
C:\projects>

가상 환경 진입

C:\projects>C:\venvs\yoursite\Scripts\activate
(yoursite) C:\projects>

프로젝트 yoursite 생성

(yoursite) C:\projects>mkdir yoursite

yoursite 디렉터리로 이동

(yoursite) C:\projects>cd yoursite
(yoursite) C:\projects\yoursite>

장고 프로젝트 생성

(yoursite) C:\projects\yoursite>django-admin startproject config .

장고 프로젝트가 생성되면 yoursite디렉터리 밑에는 장고에 사용하는 여러 디렉터리와 파일들이 생성된다.

개발서버(yoursite) 구동 및 웹 사이트 접속

python manage.py runserver 명령

(yoursite) C:\projects\yoursite>python manage.py runserver
Watching for file changes with StatReloader
Performing system checks...

System check identified no issues (0 silenced).

You have 18 unapplied migration(s). Your project may not work properly until you apply the migrations for app(s): admin, auth, contenttypes, sessions.
Run 'python manage.py migrate' to apply them.
February 11, 2022 - 23:01:39
Django version 3.1.3, using settings 'config.settings'
Starting development server at http://127.0.0.1:8000/
Quit the server with CTRL-BREAK.

위의 http://127.0.0.1:8000/ 를 통해 웹 사이트 접속

[ctrl + c] 키를 누르면 개발서버 구동 취소

언어 / 시간 세팅

[파일이름 : C:/projects/yoursite/config/settings.py] 수정

(생략)
LANGUAGE_CODE = #'ko-kr'

TIME_ZONE = #'Asia/Seoul'
(생략)

한국어와, 한국 서울시간으로 장고 서버환경이 바뀐다.

1. 포스팅을 왜 하냐?

공부한 것을 정리하며, 공부 방향을 올바르게 잡기 위하여.

혹시 모를 저작권문제를 우려해서.

 

Study 목적

머신러닝, 딥러닝, SQL 등을 공부 한 후, 장고를 통해 웹 서비스로 제공하는 프로젝트를 수행하기 위해 장고를 공부하게 되었다. 플라스크보단 탄탄하고, 자바보단 쉽다고 생각하여 장고를 골랐다. 하지만 결국 다 공부하게 되지않을까?

 

내용

데이터기반 인공지능 시스템 엔지니어 양성 과정 중 점프 투 장고 교재를 사용하여 실습한 내용이다.

거의 교재의 소스코드가 사용되었지만, 나에게 맞춰 최적화(?)한 내용이다.

내 글이 이해가 안된다면, 참고자료의 위키독스 자료를 이용하면 더 잘 이해될거에요..

 

참고자료

-박응용, 점프 투 장고(이지스퍼블리싱,2021), https://wikidocs.net/book/4223

 

점프 투 장고

**점프 투 장고 오프라인 책 출간 !! (2020.12)** * [책 구입 안내](https://wikidocs.net/105844)

wikidocs.net

-데이터기반 인공지능 시스템 엔지니어 양성 과정 교육자료

+ Recent posts