Discover us

About us

Projects

Blog

Events

Members

Development Blog

GDGoC CAU 개발자와 디자이너의 작업 과정과
결과물을 공유하는 공간입니다.

어떻게 프로젝트를 시작하게 되었고,
진행하면서 느낀 개발자와 디자이너의
생생한 스토리를 직접 확인해보세요!

Development

Django 스터디 1주차

  • #Back-End
  • Seoyeon Lee
  • 2024. 7. 20.

Django 스터디 1주차

Django 스터디 1주차

Django 소개

  • 파이썬 기반으로 작성된 오픈소스 웹 어플리케이션 프레임워크
  • 장고 공식 사이트 : [https://www.djangoproject.com] (https://www.djangoproject.com)
  • 장고의 목표 : 데이터베이스 기반 웹 사이트를 보다 편리하게 작성하는 것
  • 내장된 기능만을 이용하여 빠르게 웹 개발을 할 수 있다는 것이 장점
  • MVT 패턴을 따름

MVT 패턴

  • M(Model) + V(View) + T(Template)
  • 웹 어플리케이션 개발 영역을 크게 3가지로 나눔으로써 독립적으로 개발 가능

Model

  • 데이터를 다루는 영역
  • 데이터베이스에 적용될 모델 설계

View

  • 웹 어플리케이션에서 데이터들이 처리되는 로직 정의
  • 데이터를 처리할 함수 정의

Template

  • 사용자가 보게 되는 웹 페이지의 모습을 구성
  • 주로 html, css, javascript 등을 이용한 클라이언트 정적 웹 페이지를 작성

블로그 홈 화면 구성

App 생성

  • App들이 모여서 하나의 장고 프로젝트를 구성
python manage.py startapp blogapp
blogapp이라는 이름의 앱 생성
  • 생성한 blogapp을 장고가 인식하게 하기 위해서 settings.py 설정
notion image
app 등록
INSTALLED_APPS에 프로젝트에서 사용하는 앱을 등록

templates 구성

  • templates에서 홈 화면을 구성하기 위한 html 문서를 관리
notion image
templates 이동
blogapp 안에서 홈 화면을 띄울 것이므로 templatesblogapp으로 옮김
  • html 문서 작성
    • <html lang="en"><head> <meta charset="UTF-8"> <title>Title</title></head><body>안녕하세요. 중앙대학교 GDSC.</body></html>
      index.html 작성

views.py & urls.py

  • views.py
    • 파이썬 문법을 활용하여 여러 함수들 생성
    • 생성함 함수들을 이용하여 자신이 원하는 형태로 데이터를 처리한 뒤, 특정 html로 데이터를 보냄
    • def index(request): return render(request, 'index.html')
      render 함수를 통해 요청을 index.html 문서로 리턴
  • urls.py
    • view.py에서 생성한 index 함수를 urls.py에서 연결
    • urlpatterns = [ path('admin/', admin.site.urls), path('', blogapp.views.index, name='index'),]
    • path 함수
      • 첫번째 인자 ’’ : 내 블로그 홈페이지의 주소를 입력할 때 아무것도 입력하지 않음 즉, ’http://www.myblog.com’으로 접속하면 내가 작성한 index.html 문서가 보임
      • 두번째 인자 blogapp.views.index : 내가 생성한 index 함수를 적용시킴
      • 세번째 인자 name=‘index’ : 함수를 적용시키고 이름을 명명하면, 추후에 html 파일에서 이 이름으로 url 값을 불러올 수 있음

부트스트랩

  • 웹 사이트를 쉽게 만들 수 있게 도와주는 html,css,js 프레임워크
  • 하나의 css로 휴대폰, 태블릿, 데스크탑까지 다양한 기기에서 작동함
  • 즉, 부트스트랩을 이용해 예쁜 페이지를 쉽게 구성할 수 있음

정적 파일

  • 부트스트랩 html은 css 파일을 별개로 가지고 있기 때문에 이를 따로 관리해야 함
  • 정적 파일은 웹 페이지를 만들 때, 쓰임이 정해져있는 파일들이므로 개발 단계에서 해당 파일들을 관리
  • css 파일, jpg와 같은 이미지 파일, javascript 파일 등
  • 정적 파일과 반대되는 개념은 media 파일
    • media 파일은 사용자가 업로드하는 파일
    • 개발 단계에서 관리할 수 없으므로 따로 분류하여 관리
    • notion image
static
blogapp 내에 static 디렉토리를 생성하여 부트스트랩 html의 css 파일을 관리
  • settings.py 설정
    • STATICFILES_DIRS = [ os.path.join(BASE_DIR, 'blogapp', 'static')]STATIC_ROOT = os.path.join(BASE_DIR, 'static')
      settings.py 맨 아래 라인에 위의 코드를 입력하여 정적 파일의 위치를 지정
      python manage.py collectstatic
      터미널에서 정적 파일들을 한 곳으로 모아주는 명령어 입력
  • index.html 수정
notion image
index.html
부트스트랩 html의 코드를 복사하여 장고 프로젝트의 index.html에 붙여넣기

장고 템플릿(template) 언어

  • 장고 템플릿 언어는 장고로 개발할 때, html 템플릿에서 사용할 수 있는 템플릿 규칙 또는 문법
  • 템플릿 변수, 템플릿 필터, 템플릿 코멘트 등
  • 템플릿 변수
    • {{ }}로 구성
    • ex. {{ section.title }}
    • 템플릿 변수를 사용하여 html 문서 상에서도 어떠한 객체의 속성들에 접근할 수 있고, 이를 출력할 수 있음
  • 템플릿 필터
    • 템플릿 변수 다음에 ’|’를 그은 다음 적용하고자 하는 필터를 명시
    • ex. {{ story.headline | upper }}의 ‘upper’
    • 템플릿 변수의 값을 특정 형식으로 변환할 때 사용
  • 템플릿 태그
    • {% %}로 구성
    • ex. {% endblock %}, {% if %}
    • html은 프로그래밍 언어가 아닌 마크업 언어이므로 프로그래밍적 로직을 구현할 수 없으나 if문, for문과 같은 템플릿 태그를 사용하면 구현 가능
  • 템플릿 코멘트
    • 두 가지 코멘트 형식
        1. {# #} : 한 줄 코멘트
        1. {% comment %}, {% endcomment %} : 여러 줄 코멘트
    • html 문서 상에서 코멘트가 필요할 때 사용
    • 주석과 유사한 역할
    • 웹 사이트에서 출력되지 않음

블로그 메인 화면 구성

templates 구성

  • 블로그 홈 화면 구성과 동일한 방식
notion image
navbar-template
  • template 폴더에서 blogMain.html 문서를 생성한 후, 부트스트랩의 html 코드를 복사하여 붙여넣기
  • 부트스트랩의 css 파일을 복사하여 static - css에 붙여넣기
  • ’python manage.py collectstatic’를 입력하여 정적 파일을 한 곳으로 모음

views.py & urls.py

  • 블로그 홈 화면 구성과 동일한 방식
  • views.py
    • def blogMain(request): return render(request, 'blogMain.html')
  • urls.py
    • urlpatterns = [ path('admin/', admin.site.urls), path('', blogapp.views.index, name='index'), path('blogMain/', blogapp.views.blogMain, name='blogMain'),]

데이터베이스

  • 블로그에서 글을 작성하면 그 내용들이 서버에 저장되어야 하고, 저장된 데이터들이 다시 블로그 안에서 보여야 함
  • 데이터들을 서버에 저장하기 위해 데이터베이스 이용
  • 글쓰기 항목의 모델 설계
    • from django.db import modelsclass Blog(models.Model): title = models.CharField(max_length=100) pub_date = models.DateTimeField() body = models.TextField()
      models.py 파일에 위의 코드를 작성하여 간단한 글쓰기 모델 설계
  • 모델 데이터베이스 적용
    • python manage.py makemigrations python manage.py migrate
      설계한 모델을 데이터베이스에 적용하기 위해 터미널에서 위의 명령어 입력

Admin Page

  • admin 페이지에서 설계한 모델이 데이터베이스에 적용되었는지 확인 가능
  • Tools - Run manage.py Task에서 createsuperuser를 입력하여 관리자 계정 생성
  • admin 페이지에 블로그 모델 등록
    • from django.contrib import adminfrom .models import Blog# Register your models here.admin.site.register(Blog)
      admin.py 파일에 블로그 모델 등록
      notion image
admin-page
admin 페이지에서 블로그를 추가하였을 때, 블로그 객체가 생성된다면 성공!

forms.py

  • 글쓰기에 사용할 폼 생성
  • 데이터베이스 모델에서 title, pub_date, body 항목을 가져오는 작업을 수행하기 위함
  • blogapp 디렉토리 내에 admin.py 생성
    • from django import formsfrom .models import Blogclass CreateBlog(forms.ModelForm): class Meta: model = Blog fields = ['title', 'pub_date', 'body']
    • 장고에서 Meta 클래스는 내부 클래스로 활용되며, 기본 필드 값을 재정의할 때 사용
    • blog로부터 모델을 가져오고, 그 중 ‘title’, ‘pub_date’, ‘body’ 항목을 가져온다는 의미
  • 글쓰기에 사용되는 폼을 띄워줄 템플릿 생성
    • blogapp - templatescreateBlog.html 작성
    • views.py
      • from .forms import CreateBlogdef createBlog(request): form = CreateBlog() return render(request, 'createBlog.html', {'form': form})
      • 불러들인 폼을 createBlog.html로 보내기 위해 form 객체를 생성
      • render(request, ‘템플릿’, context) 형식
        • context는 딕셔너리 자료형의 형태
        • createBlog.html 문서에 딕셔너리 자료형을 보내게 되고, createBlog.html에서는 장고 템플릿 변수를 이용하여 값을 출력
    • urls.py
      • urlpatterns = [ path('admin/', admin.site.urls), path('', blogapp.views.index, name='index'), path('blogMain/', blogapp.views.blogMain, name='blogMain'), path('blogMain/createBlog/', blogapp.views.createBlog, name='createBlog'),]

템플릿-DB 연동

  • 사용자들이 입력한 데이터를 전송하기 위해 createBlog.html에 데이터 전달 폼 구축
    • <form method="POST"> {{ form.as_p }} <input type="submit" value="저장"/></form>
      ‘POST’ 방식으로 폼 안의 데이터가 전달되고, 데이터를 제출하기 위해 ‘submit’ 타입 사용
  • views.py 파일 내의 createBlog() 함수 수정
    • from django.shortcuts import render, redirectdef createBlog(request): if request.method == 'POST': form = CreateBlog(request.POST) if form.is_valid(): form.save() return redirect('blogMain') else: return redirect('index') else: form = CreateBlog() return render(request, 'createBlog.html', {'form': form})
    • redirect() 함수는 render() 함수와 유사하나 템플릿에 값을 전달하는 것이 아닌 단순히 특정 url 혹은 프로젝트 내의 문서로 이동시키고자 할 때 사용
        1. createBlog.html에서 저장을 누르면 데이터들이 POST 방식으로 넘어옴
        1. CreateBlog() 폼에 값을 전달한 상태로 form 객체 생성
        1. 데이터들이 올바른 형식이면(form.is_valid()), 데이터베이스에 저장(form.save())
        1. 그 후에 블로그 메인 화면으로 이동(redirect(‘blogMain’))
  • POST 데이터 전달 과정에서 보안을 위해 createBlog.html 파일에 ‘{% csrf_token %}’ 추가

템플릿 상속

  • html 문서 중 기본 뼈대가 되는 문서를 기본 템플릿으로 정하고, 다른 문서에서 기본 템플릿의 코드가 필요하면 상속하여 가져다 씀
  • ’base.hteml’로 설정
  • navbar의 내용을 상속받도록 blogMain.html의 코드를 base.html에 붙여넣기
  • 기본 템플릿의 위치가 변경되었으므로 settings.pyTEMPLATES 수정
  • blogMain.html에서 아래 내용 추가
    • {% extends 'base.html' %}{% block content %}{% endblock %}
    • ’extends ~’는 base.html을 상속받는다는 의미
    • ‘block ~’과 ’endblock ~’ 사이에는 blogMain.html만의 내용을 나타내는 코드 작성
  • 위와 같은 방식으로 createBlog.html 파일 수정

모델 재설계

  • 데이터베이스 모델 형태 변경
      1. 제목
      1. 날짜 - 별도로 입력하지 않고, 저장을 누르면 자동 입력
      1. 작성자
      1. 내용 - 글자의 색깔, 폰트, 크기 등을 변경하고, 이미지 파일을 업로드
  • 위의 내용에 맞게 models.pyforms.py 수정

CKEditor

  • ’body’의 글자를 예쁘게 꾸밀 수 있는 텍스트 편집기
  • 위지위그(WYSIWYG: What You See Is What You Get) 방식 : 블로그나 웹 페이지에서 글을 쓸 때, 눈에 보이는 글씨의 모양 그대로 문서 편집을 할 수 있는 것
  • CKEditor Tool 설치
    • pip install django-ckeditor
      터미널에 위의 명령어를 입력하여 CKEditor 설치
  • settings.py 파일 내의 INSTALLED_APPS에 ‘ckeditor’, ‘ckeditor_uploader’ 등록
  • 사용자들이 업로드하는 파일을 관리하기 위해 settings.py에 ‘media’ 루트 설정
    • MEDIA_URL = '/media/'MEDIA_ROOT = 'media/'
      settings.py 맨 아래에 위의 코드 추가
  • urls.py 수정
    • from django.conf.urls import includepath('ckeditor/', include('ckeditor_uploader.urls')),
      ckeditor_uploader가 url을 참조할 수 있도록 설정
      from django.conf import settingsfrom django.conf.urls.static import staticurlpatterns += static(settings.MEDIA_URL, document_root=settings.MEDIA_ROOT)
      MEDIA 경로를 참조하기 위해 위의 문장 추가
  • bloggapp - models.py 수정
    • from ckeditor.fields import RichTextFieldfrom ckeditor_uploader.fields import RichTextUploadingFieldbody = RichTextUploadingField()
  • ‘collectstatic’ 명령어를 입력하여 정적 파일들을 모아준 후, 모델 적용

글쓰기 페이지 꾸미기

  • CKEditor 폼을 적용시켜 파일 업로딩 기능을 글쓰기 페이지에 적용
  • forms.pycreateBlog.html 파일 수정

블로그 메인 화면 출력

  • bloggapp - models.py에서 blogMain() 함수 수정
    • from .models import Blogdef blogMain(request): blogs = Blog.objects.all() return render(request, 'blogMain.html', {'blogs': blogs})
    • 데이터베이스에 저장된 객체를 모두 가리키는 ‘blogs’ 객체 생성
    • ‘blogs’ 객체를 blogMain.html로 보냄
  • blogMain.html 수정
{% extends 'base.html' %}{% block content %} <br> {% for blog in blogs %} <main role="main" class="container"> <div class="jumbotron"> <h1>제목 : {{ blog.title }}</h1> <br> <h4>작성일 : {{ blog.pub_date }}</h4> <br> <h4>작성자 : {{ blog.author }}</h4> <br> <p class="lead">{{ blog.body }}</p> <br> <a class="btn btn-lg btn-primary" href="{{ site.baseurl }}/docs/{{ site.docs_version }}/components/navbar/" role="button">View navbar docs &raquo;</a> </div> </main> {% endfor %}{% endblock %}
  • 넘겨받은 ‘blogs’ 객체에서 템플릿 태그 for를 사용하여 반복문을 돌며 하나씩 블로그 객체 반환
  • 템플릿 변수를 이용하여 각 블로그 객체의 제목, 작성일, 작성자, 내용을 출력
  • 내용에 원하지 않는 태그가 섞여서 나오는 문제를 해결하기 위해 장고 템플릿 필터 ‘safe’ 사용
    • blogMain.html에 ‘{{ blog.body | safe }}’ 추가
Django 스터디 1주차