Django framework란? (feat. MTV pattern, 실제 tutorial)

idle-danie·2023년 5월 12일
2
post-thumbnail

본 글은 Django framework 공식문서에서 소개하는 설치 과정과 제시하는 MTV패턴을 중심으로 tutorial의 핵심 요소를 정리한 글입니다.

What is Django?

Django는 파이썬으로 작성된 고수준 웹 프레임워크로, 신속한 개발과 깔끔한 디자인을 가능하게 합니다. Django"batteries-included" 철학을 따르며, 많은 기능을 내장하여 웹 개발에 필요한 거의 모든 것을 제공합니다.

Django는 MTV 패턴을 따릅니다. MTV는 Model-Template-View의 약자로, 흔히 우리가 아는 MVC(Model-View-Controller) 패턴의 변형입니다. Django에서는 View가 실제로 비즈니스 로직을 처리하는 것이 아니라, 템플릿 시스템을 사용하여 데이터를 표시하는 역할을 합니다.

  • Model: 데이터베이스 구조를 정의합니다. 데이터의 필드와 동작을 정의하며, 데이터베이스와의 상호 작용을 관리합니다.
  • Template: 사용자에게 표시될 화면을 정의합니다. HTML과 Django 템플릿 언어를 사용하여 데이터를 렌더링합니다.
  • View: 요청을 처리하고 적절한 템플릿을 선택하여 응답을 반환합니다. 비즈니스 로직을 구현하고, 모델과 템플릿을 연결합니다.

이제 공식문서에서 제시하는 가이드라인에 따라 Django를 설치해보고, 간단하게 구성 요소를 살펴봅시다.

초기 세팅

가상환경

기존 환경에서 실행해도 상관은 없지만 여러 프로젝트의 버젼 충돌로 인한 에러를 방지하기 위하여 virtual environment를 구축하는것이 바람직하다

가상환경 생성

py -m venv project-name

가상환경 활성화

project-name\Scripts\activate.bat

가상환경 비활성화

deactivate

django 설치

py -m pip install Django

장고 버젼 확인

django-admin –version

장고 프로젝트 생성

$ django-admin startproject mysite

장고 서버 실행

$ python manage.py runserver

앱 생성

$ python manage.py startapp polls ## polls -> App 이름

생성된 앱을 서버에서 구축하기 위해서는 urls path와 settings를 관리해야 합니다.

참고로, 아래에서 언급되는 urls.py파일은 쉽게 설명하면 API request path를 관리하는 파일이라고 보면 됩니다. (ex: Node.js 프로젝트에서 관리하는 index.ts 파일)

프로젝트 디렉토리의 urls.py

from django.contrib import admin
from django.urls import path, include
urlpatterns = [
    path("admin/", admin.site.urls),
    path("polls/", include('polls.urls'))
]

특정 앱 디렉토리 (ex: polls)의 urls.py

from django.urls import path
from . import views
urlpatterns = [
    path('',views.index, name='index')
    path('some_url',views.some_url)
]

프로젝트 디렉토리의 settings.py

INSTALLED_APPS = [
    'django.contrib.admin',
    'django.contrib.auth',
    'django.contrib.contenttypes',
    'django.contrib.sessions',
    'django.contrib.messages',
    'django.contrib.staticfiles',
    'polls.apps.PollsConfig',
]

Models

장고의 model은 RDB의 개념이라고 생각하면 쉽다.
따라서 SQL과 같이 schema를 생성하고 attribute을 추가하고 이에 대한 filtering이 가능하다.

앱 디렉토리의 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 = models.ForeignKey(Question, on_delete=models.CASCADE)
    choice_text = models.CharField(max_length=200)
    votes = models.IntegerField(default=0)

Templates

화면단 구현에 필요한 각각의 html 파일은 template 디렉토리에서 보통 관리한다.

index.html 예시

{% if questions %}
<ul>
    {% for question in questions %}
        <li>{{question}}</li>
    {% endfor %}
</ul>
{% else %}
<p>no questions</p>
{% endif %}

Views

views.py

각각의 html파일을 함수 단위로 manage한다.

from .models import *
from django.shortcuts import render

def index(request):
    latest_question_list = Question.objects.order_by('-pub_date')[:5]
    context = {'questions': latest_question_list}
    return render(request, 'polls/index.html', context)
    
def detail(request, question_id):
    question = Question.objects.get(pk=question_id)
    return render(request, 'polls/detail.html', {'question': question})

참고로, render는 간단하게 말하면 html파일을 화면에 보이게 만들어 주는 것이라고 이해하면 된다.

urls.py

추가한 view의 결과를 보기 위해서는 path를 추가해야한다

from django.urls import path 
from . import views  

app_name = 'polls'

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

Error 처리

404에러: http에서 요청한 페이지를 찾을 수 없을 때 생기는 에러

404 에러 방지

def detail(request, question_id):
    
    try:
        question = Question.objects.get(pk=question_id)
    except Question.DoesNotExist:
        raise Http404("Question does not exist")
    
    question = get_object_or_404(Question, pk=question_id)
    return render(request, 'polls/detail.html', {'question': question})

서버에서 요청을 동시에 처리할 때 발생할 수 있는 에러 방지

Solve: 두개의 서버가 아닌 하나의 DB에서 처리

def vote(request, question_id):
   question = get_object_or_404(Question, pk=question_id)
   try:
       selected_choice = question.choice_set.get(pk=request.POST['choice'])
   except (KeyError, Choice.DoesNotExist):
       return render(request, 'polls/detail.html', {'question': question, 'error_message': f"선택이 없습니다. id={request.POST['choice']}"})
   else:
       selected_choice.votes = F('votes') + 1
       selected_choice.save()
       return HttpResponseRedirect(reverse('polls:index'))

Admin

  • django에는 관리자 페이지 및 관리자 기능을 할 수 있는 admin.py를 제공한다
  • 관리자 페이지에서 보여질 모델의 필드, 필터링 기준, 검색 기준 등을 설정할 수 있으며, 모델에 대한 CRUD(CREATE, READ, UPDATE, DELETE) 작업을 수행하는 메소드도 정의할 수 있다.
  • 쉽게 말하면 Admin을 활용하여 DB의 내용 관리(CRUD)를 손쉽게 할 수 있다는 것이다.

CRUD를 위한 Admin page 커스터마이즈

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

admin.site.register(Choice)

class ChoiceInline(admin.TabularInline):
    model = Choice
    extra = 3


class QuestionAdmin(admin.ModelAdmin):
    fieldsets = [
        ('질문 섹션', {'fields': ['question_text']}),
        ('생성일', {'fields': ['pub_date'], 'classes': ['collapse']}),        
    ]
    readonly_fields = ['pub_date']
    inlines = [ChoiceInline]
    list_filter = ['pub_date']
    search_fields = ['question_text', 'choice__choice_text']
    
admin.site.register(Question, QuestionAdmin)

지금까지 공식문서를 따라, Django 아키텍처 내에서 MTV패턴이 대략적으로 어떤 구조로 구현되고, 에러에 대한 관리와 admin 기능을 어떻게 코드로 관리하는지에 대해 알아보았다.

이후, tutorial에서 제시하는 가이드라인을 전체 구현한 코드는 아래 github repository에 업로드 해놓았습니다 :)
GitHub - idle-danie/django_study: django_study_tutorial

참고문헌

https://www.djangoproject.com/start/

profile
wanna be idéal DE

0개의 댓글

관련 채용 정보