Jasontreks Blog

DM 보내기


Send

Django App

Django는 ORM을 이용해 실시간으로 변화하는 데이터들을 반영한 동적인 페이지 구성할 수 있으며, Form을 이용해 입력과 요청을 쉽게 처리할 수 있게 한다. 뷰 함수는 실제 동작을 구현하는 부분이고, 템플릿 문법은 이를 HTML에 반영할 수 있게 한다.

Django 웹앱의 핵심 구성요소들

웹 애플리케이션으로서 작동하기 위해 다음 네개가 꼭 필요하다.

  • : 요청 처리 함수. 빈환으로는 페이지를 렌더링하거나 기타 백엔드 동작을 구현함.
  • 템플릿: 폼이나 DB 튜플등을 context로 넘겨, 파이썬과 동일한 문법으로 html에 적용할 수 있도록 함
  • : 사용자의 입력 폼을 빠르게 구성할 수 있게 클래스로 구성할 수 있고, 이 역시 템플릿으로 웹페이지 렌더링 시 간단하게 반영할 수 있음
  • ORM: DB 테이블을 파이썬 클래스로 정의하고 질의 역시 모듈이 제공하는 기능으로 처리할 수 있도록 하는 Django 기능.

이 네가지가 제대로 구성되어야 원하는 작업을 웹앱에 구현할 수 있음.

이번 프로젝트의 요구사항 중 하나인 텍스트 추가 및 임베딩 저장 기능을 Django 웹앱에서 구현한다면, 위 네가지 요소를 다음과 같이 활용할 수 있으리라 추측할 수 있음.

  • 텍스트 입력창: Form + 템플릿
  • 폼 submit -> views.py에서 요청 처리:
  • 텍스트 파일 저장 및 임베딩: 함수에서 모듈 불러와서 처리
  • 파일 정보 RDB에 저장: 함수에서 ORM으로 처리
  • 벡터DB에 반영된 파일 표시: ORM + 템플릿

앱 디렉터리 내의 views.py에서 구현

from django.shortcuts import render, redirect
from .form import ContactForm

# 홈 화면을 렌더링하는 뷰 함수.
# URL에 어떤 뷰 함수를 호출할지 연결지을 수 있는데 (URL 라우팅)
# 빈 URL('')에다가 이 함수를 연결지으면, 메인화면 출력이 됨
def home_view(request):
    return render(request, 'core/home.html')

# submit된 폼을 처리하고(request.method == 'POST')
# submit이 없었다면 빈 form을 생성
# context로 넘겨 연락처 입력 페이지 렌더링(contact.html에서 템플릿 문법으로 context 객체 사용)
def contact_view(request):
    if request.method == 'POST':
        form = ContactForm(request.POST)
        if form.is_valid():
            form.send_email()
            return redirect('contact-success')
    else:
        form = ContactForm()
    context = {'form': form}
    return render(request, 'core/contact.html', context)

# 위 contact_view에서 redirect('contact-success') 가 반환될 경우 이 뷰 함수가 호출되는데
# URL 라우팅 시 설정해둔 이름을 직접 지목하는것이다.('contact-success')
def contact_success_view(request):
    return render(request, 'core/contact_success.html')

템플릿

템플릿의 주된 활용 목적은 다음과 같다.

  1. 정적 자산(images, js, css) 로드
  2. 뷰 함수에서 넘겨준 context 사용
  3. URL라우팅에서 설정한 URL 사용

정적 자산 및 URL 예제

<!-- 정적 자산 로드 -->
{응 load static 응}

<!DOCTYPE html>
<html lang="ko">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>HOME</title>
	<!-- 정적 자산 중 스타일시트 불러오기 -->
    <link rel="stylesheet" href="{응 static 'styles/styles.css' 응}">
</head>
<body>
	<div class="centered-content">
		<!-- 정적 자산 중 이미지 불러오기 -->
		<img src="{응 static 'images/logo.png' 응}" alt="logo">
		<!-- contact라는 이름으로 설정한 URL 라우팅을 폼 액션 적용. 
		submit 시 이에 해당하는 뷰 함수가 호출됨 -->
		<form action="{응 url 'contact' 응}" method="get">
			<button type="submit" class="btn">Click to Enter Form</button>
		</form>
	</div>
</body>
</html>

context 사용 예제

{응 load static 응}

 <!DOCTYPE html>
 <html lang="kr">
 <head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Contact Us</title>
    <link rel="stylesheet" href="{응 static 'styles/styles.css' 응}">
 </head>
 <body>
    <h1>Contact Us</h1>
    <form method="POST">
        {응 csrf_token 응}
	<!-- contact_view 함수 반환 시 넘긴 context (context = {'form': form})
	이 중 form을 사용 (p태그로 감싸서 출력) -->
        { form.as_p } 
        <button type="submit">Submit</button>
    </form>
 </body>
 </html>

앱 디렉터리에 from.py 파일을 하나 추가하고 다음과 같이 작성

from django import forms

# 테스트를 위한 간단한 연락처 입력 폼
class ContactForm(forms.Form):
    name = forms.CharField(max_length=100)
    email = forms.EmailField()
    message = forms.CharField(widget=forms.Textarea)

	# submit 이후 백단에서 자체적으로 처리할 기능이 있다면 메서드로 정의
    def send_email(self):
        print(f"Sending email from {self.cleaned_data['email']} with message: {self.cleaned_data['message']}")

이제 views.py에서 이 클래스를 임포트하고 사용

from django.shortcuts import render, redirect
from .form import ContactForm # 만들어둔 폼 클래스 임포트

def home_view(request):
    return render(request, 'core/home.html')

def contact_view(request):
	# contact.html에서 submit -> POST: 
    if request.method == 'POST':
        form = ContactForm(request.POST)
        if form.is_valid():
            form.send_email()
            return redirect('contact-success')
	# contact.html 페이지 로드 -> GET 
    else:
        form = ContactForm()
	# context로 넘김 (키값 'form': 템플릿 문법에서 사용할 변수명)
    context = {'form': form}
    return render(request, 'core/contact.html', context)

def contact_success_view(request):
    return render(request, 'core/contact_success.html')

ORM

바로 이전의 포스트에서 MySQL과 연동하는 방법을 소개하면서 짚고 넘어갔으므로 개념만 다시 정리하자면

SQL 서버 연결 -> DB생성 및 테이블 구성 -> 필요한 질의 다 작성후 함수화 이 과정을 django 패키지에서 미리 다 만들어놓고 제공하는 것이라 보면 된다.

테이블을 만들 때 역시 클래스로 만들어 스키마를 정의할 수 있는데, 이를 Model이라 한다. Model을 객체화하여 값을 넣으면 그에 해당하는 튜플이 만들어지는 개념이다. Model 객체의 메서드인 save()를 호출하기만 하면 DB의 테이블에 해당 튜플이 저장된다. 내부적으로 INSERT문이 실행되는 것.

요약하자면, ORM은 파이썬의 객체지향적 특성을 활용해 SQL문법 없이 DB를 다룰 수 있는 것. 또 템플릿 언어를 활용해 웹페이지에 동적으로 데이터들을 반영할 수 있도록 하는 것이다.

모델은 앱 디렉터리 내의 models.py에서 정의한다.

from django.db import models

class Student(models.Model):
    name = models.CharField(max_length=64)
    age = models.IntegerField()
    student_id = models.IntegerField()