<?xml version="1.0" encoding="UTF-8"?><rss xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:content="http://purl.org/rss/1.0/modules/content/" xmlns:atom="http://www.w3.org/2005/Atom" version="2.0"><channel><title><![CDATA[jimin's blog]]></title><description><![CDATA[42seoul member]]></description><link>https://jimin52.hashnode.dev</link><generator>RSS for Node</generator><lastBuildDate>Wed, 16 Sep 2026 04:09:52 GMT</lastBuildDate><atom:link href="https://jimin52.hashnode.dev/rss.xml" rel="self" type="application/rss+xml"/><language><![CDATA[en]]></language><ttl>60</ttl><item><title><![CDATA[일주일동안 장고하기 3일차]]></title><description><![CDATA[복습 및 환경설정 정리
어제 하던 작업을 이어하던 도중 python 버전이 안 맞는 일이 발생했다. venv 환경이 python 2.7 로 변경되어 있었는데 원인은 모르겠다. 개발하다보면 불가사의한 일들이 발생하곤 한다.. 기존 장고 버전은 5.0 이었는데 이 버전은 파이썬 3.7 환경에서 실행될 수 없었다... 어제는 어떻게 실행된 건지 또한 알 수 없다. 아무튼 django 버전을 3.2 로 다운그레이드하고 파이썬 3.7 환경에서 다시 시작...]]></description><link>https://jimin52.hashnode.dev/3</link><guid isPermaLink="true">https://jimin52.hashnode.dev/3</guid><category><![CDATA[Django]]></category><category><![CDATA[Tutorial]]></category><dc:creator><![CDATA[Ji-Hyuck, Min]]></dc:creator><pubDate>Tue, 05 Mar 2024 06:26:18 GMT</pubDate><enclosure url="https://cdn.hashnode.com/res/hashnode/image/upload/v1709619809015/3a81bfea-0298-47a1-a4e7-b7bdc8be0a7d.png" length="0" type="image/jpeg"/><content:encoded><![CDATA[<h2 id="heading-67o17iq1iouwjydtmzjqsr3shktsojug7kcv66as">복습 및 환경설정 정리</h2>
<p>어제 하던 작업을 이어하던 도중 python 버전이 안 맞는 일이 발생했다. venv 환경이 python 2.7 로 변경되어 있었는데 원인은 모르겠다. 개발하다보면 불가사의한 일들이 발생하곤 한다.. 기존 장고 버전은 5.0 이었는데 이 버전은 파이썬 3.7 환경에서 실행될 수 없었다... 어제는 어떻게 실행된 건지 또한 알 수 없다. 아무튼 django 버전을 3.2 로 다운그레이드하고 파이썬 3.7 환경에서 다시 시작했다.</p>
<p>그리고 가상환경 관련 파일을 한번에 핸들링하기 어려워서 디렉토리를 프로젝트 내부에 포함시키게 되었다.</p>
<p>기존 디렉토리 구조는 다음과 같았다.</p>
<pre><code class="lang-plaintext">.
├── README.md
├── requirements.txt
├── django-site
│   ├── db.sqlite3
│   ├── manage.py
│   ├── mysite
│   └── polls
├── bin
├── include
├── lib
└── pyvenv.cfg
</code></pre>
<p>venv 디렉토리를 삭제하기 위해 프로젝트 내부에 가상환경을 설정하게 되었다.</p>
<pre><code class="lang-plaintext">.
├── README.md
├── django-site
├── requirements.txt
│   ├── db.sqlite3
│   ├── manage.py
│   ├── mysite
│   └── polls
└── venv
    ├── bin
    ├── include
    ├── lib
    └── pyvenv.cfg
</code></pre>
<p>바뀐 구조는 venv 환경을 삭제하고 다시 실행하기 유리하다는 장점이 있다.</p>
<p>새로 개발환경을 구성하니 (삭제하고 다시 clone 했다) admin 계정과 저장한 데이터들이 사라져있었다. 덕분에 데이터를 dump 하는 방법을 살펴볼 수 있었다. dump 파일을 git 에 올렸다가 admin 계정정보가 노출되면 어떡하나 고민했지만 비밀번호는 해싱된 채로 저장된다고 한다. 그래도 가급적이면 db 관련정보는 노출하면 안될 것이다. <a target="_blank" href="https://docs.djangoproject.com/en/5.0/ref/django-admin/#dumpdata">data dump 하는 방법</a></p>
<p>4장까지 진도를 다시 복습해보고 5장을 시작하게 되었다. 3, 4 장은 view, template 관련 문법이라 지루했지만 5장은 관심이 많은 테스트 코드 관련 문서였다.</p>
<h2 id="heading-5">5장 테스트 코드</h2>
<p>테스트 코드의 중요성은 아무리 강조해도 지나치지 않는다. 코드의 작동이 엄밀해야 할수록 (작성된 코드가 돈을 벌어 올 수록) 테스트의 중요성은 더욱 커진다. 에러 케이스를 예방하는 데 도움을 주고 테스트를 자체가 요구사항을 의미하기 때문에 요구사항을 보장한다. 그리고 테스트 가능한 코드는 그 자체로 모듈화를 보장하고 잘 모듈화된 코드는 재사용성과 기능의 가독성을 보장한다. 테스트 코드를 만드는 것은 어렵지만, 어려운 만큼 큰 보상이 있다는 뜻이다. 귀찮아도 열심히 만들자.</p>
<p>테스트를 위해 <code>polls/</code><a target="_blank" href="http://test.py"><code>test.py</code></a> 파일을 만들었다.</p>
<p>django.test 모듈에서 TestCase 라는 클래스를 불러와서 사용한다.</p>
<pre><code class="lang-python"><span class="hljs-keyword">from</span> django.test <span class="hljs-keyword">import</span> TestCase
</code></pre>
<p>여기서는 이전에 만들었던 <code>Question</code> 모델의 <code>was_published_recently()</code> 함수에 대한 테스트를 작성한다. <code>was_published_recently()</code> 함수는 해당 객체가 현재 날짜에서 1일 안에 작성되면 <code>True</code> 를 반환하는 함수이다. 여기서 작성하려는 테스트는 하루 이내에 작성된 객체는 <code>True</code> 를 반환 하는지, 1일 이전에 추가된 객체, 미래에 추가된 객체에 대해 <code>False</code> 를 반환 하는지 검사하는 코드이다.</p>
<pre><code class="lang-python"><span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">QuestionModelTests</span>(<span class="hljs-params">TestCase</span>):</span>
    <span class="hljs-function"><span class="hljs-keyword">def</span> <span class="hljs-title">test_was_published_recently_with_future_question</span>(<span class="hljs-params">self</span>):</span>
        <span class="hljs-string">"""
        was_published_recently() returns False for questions whose pub_date
        is in the future.
        """</span>
        time = timezone.now() + datetime.timedelta(days=<span class="hljs-number">30</span>)
        future_question = Question(pub_date=time)
        self.assertIs(future_question.was_published_recently(), <span class="hljs-literal">False</span>)

    <span class="hljs-function"><span class="hljs-keyword">def</span> <span class="hljs-title">test_was_published_recently_with_old_question</span>(<span class="hljs-params">self</span>):</span>
        <span class="hljs-string">"""
        was_published_recently() returns False for questions whose pub_date
        is older than 1 day.
        """</span>
        time = timezone.now() - datetime.timedelta(days=<span class="hljs-number">1</span>, seconds=<span class="hljs-number">1</span>)
        old_question = Question(pub_date=time)
        self.assertIs(old_question.was_published_recently(), <span class="hljs-literal">False</span>)

    <span class="hljs-function"><span class="hljs-keyword">def</span> <span class="hljs-title">test_was_published_recently_with_recent_question</span>(<span class="hljs-params">self</span>):</span>
        <span class="hljs-string">"""
        was_published_recently() returns True for questions whose pub_date
        is within the last day.
        """</span>
        time = timezone.now() - datetime.timedelta(hours=<span class="hljs-number">23</span>, minutes=<span class="hljs-number">59</span>, seconds=<span class="hljs-number">59</span>)
        recent_question = Question(pub_date=time)
        self.assertIs(recent_question.was_published_recently(), <span class="hljs-literal">True</span>)
</code></pre>
<p><code>QuestionModelTests</code> 라는 객체는 위에서 import 한 <code>TestCase</code> 클래스를 상속받아서 생성했다. 겸사겸사 python 상속에 대해서도 알아보면</p>
<pre><code class="lang-python"><span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">Country</span>:</span>
    ~~ 내용 ~~

<span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">Korea</span>(<span class="hljs-params">Country</span>):</span>
    ~~ 내용 ~~
</code></pre>
<p>위와 같이 사용하면 상속이 된다</p>
<p><code>TestCase</code> 객체를 상속받았기 때문에 <code>assertIs()</code> 같은 함수를 이용할 수 있다.</p>
<p>테스트 코드를 작성하고 다음과 같이 명령어를 입력하면 polls 앱 내부의 테스트를 자동으로 수행한다.</p>
<pre><code class="lang-bash">python manage.py <span class="hljs-built_in">test</span> polls
</code></pre>
<p>제대로 테스트를 작성했다면 다음과 같이 출력된다.</p>
<pre><code class="lang-plaintext">(venv) ➜  django-site git:(main) ✗ python manage.py test polls
Creating test database for alias 'default'...
System check identified no issues (0 silenced).
...
----------------------------------------------------------------------
Ran 3 tests in 0.001s

OK
Destroying test database for alias 'default'...
</code></pre>
<p>자동 실행되는 테스트 코드를 만들려면 몇 가지 사항을 유의해야 한다.</p>
<ul>
<li><p>파일 이름이 test 로 시작해야 함</p>
</li>
<li><p>함수 이름이 test 로 시작해야 함</p>
</li>
</ul>
<p>아래로는 view 를 테스트하는 부분이 있는데, 이 부분은 한번 해 보기만 하고 넘어갔다. <code>TestCase.client</code> 를 가지고 요청에 대한 response 를 테스트해보는 방법이었다. E2E 테스트의 일종인데 나중에 DRF 를 하며 더 상세하게 해보면 좋을 것 같다.</p>
<div data-node-type="callout">
<div data-node-type="callout-emoji">💡</div>
<div data-node-type="callout-text">그 다음에 나오는 테스트들을 따라할 때 <code>self.assertQuerySetEqual()</code> 함수가 나오는데 오타이다. <code>self.assertQuerysetEqual()</code> 로 수정해서 테스트하도록 하자.</div>
</div>

<p>해당 오류를 제보하려고 했는데 오류 제보하는 방법이 너무 복잡해서 포기했다. 티켓을 발급해서 제보하는 방식인데, 제보한다고 해서 오픈소스에 기여되는 것도 아니고 시간과 정신을 쏟아서 굳이 제보할 이유를 찾지 못했다. 심지어 이전 버전에서 해당 에러에 대한 제보가 있었는데도 불구하고 변경되지 않은 오타이다.</p>
<pre><code class="lang-plaintext">Creating test database for alias 'default'...
System check identified no issues (0 silenced).
..........
----------------------------------------------------------------------
Ran 10 tests in 0.034s

OK
Destroying test database for alias 'default'...
</code></pre>
<p>모든 테스트를 따라해보고 마무리했다.</p>
<p>6장은 app 의 static 디렉토리 내부에 css, image file 등 정적 파일을 추가하고 불러오는 내용이다. 스킵하고 넘어갔다.</p>
]]></content:encoded></item><item><title><![CDATA[일주일동안 장고하기 2일차]]></title><description><![CDATA[문서가 날아가서 다시 작성하게 되었다. 설 연휴 때문에 예정대로 진행하지 못했지만 일단 다시 시작하도록 하자.
그리고 개발환경이 바뀌어서 개발환경 세팅까지 해서 깃허브에 올리기로 하였다. 깃허브 링크 다시 작성하는 문서이기 때문에 빠르게 훑어보고 지나가기로 하겠다.
Admin 페이지
여러 프레임워크를 경험해 봤지만 이런 기능 찾아보기 힘들었다. 장고의 가장 큰 장점으로 보이는 관리자 페이지이다. 다음 명령어로 관리자 계정을 생성할 수 있다.
p...]]></description><link>https://jimin52.hashnode.dev/2</link><guid isPermaLink="true">https://jimin52.hashnode.dev/2</guid><category><![CDATA[Django]]></category><category><![CDATA[Tutorial]]></category><dc:creator><![CDATA[Ji-Hyuck, Min]]></dc:creator><pubDate>Tue, 13 Feb 2024 10:23:22 GMT</pubDate><enclosure url="https://cdn.hashnode.com/res/hashnode/image/upload/v1707895049673/f052c420-91a8-4bd1-a69f-bc2b1631782a.png" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p>문서가 날아가서 다시 작성하게 되었다. 설 연휴 때문에 예정대로 진행하지 못했지만 일단 다시 시작하도록 하자.</p>
<p>그리고 개발환경이 바뀌어서 개발환경 세팅까지 해서 깃허브에 올리기로 하였다. <a target="_blank" href="https://github.com/jimin52/django-tutorial">깃허브 링크</a> 다시 작성하는 문서이기 때문에 빠르게 훑어보고 지나가기로 하겠다.</p>
<h2 id="heading-admin">Admin 페이지</h2>
<p>여러 프레임워크를 경험해 봤지만 이런 기능 찾아보기 힘들었다. 장고의 가장 큰 장점으로 보이는 관리자 페이지이다. 다음 명령어로 관리자 계정을 생성할 수 있다.</p>
<pre><code class="lang-bash">python manage.py createsuperuser
</code></pre>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1707819619730/63912db3-2350-48a4-9876-c34b3b77f50f.png" alt /></p>
<p>마치 워드프레스 DB 관리 플러그인을 보는 느낌이 들 정도로 깔끔한 admin 페이지를 보여주었다. admin 계정 관리도 내장 명령어로 관리되었고 Object 로 추가한 데이터를 시각적으로 확인해볼 수 있다는 것이 큰 장점인 것 같다.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1707819637435/d3a49714-a1f1-4147-b84e-caf618410d0f.png" alt /></p>
<p><code>polls/</code><a target="_blank" href="http://admin.py"><code>admin.py</code></a> 파일에 이렇게 추가하면</p>
<pre><code class="lang-python"><span class="hljs-keyword">from</span> django.contrib <span class="hljs-keyword">import</span> admin

<span class="hljs-keyword">from</span> .models <span class="hljs-keyword">import</span> Question

admin.site.register(Question)
</code></pre>
<p>이렇게 멋진 edit page 를 볼 수 있다.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1707819646341/89877ca9-d885-470e-992a-826ac70496ad.png" alt /></p>
<p>무려 히스토리도 보여준다.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1707819652788/64f8e1a8-ea2e-40f5-9455-6915608c8588.png" alt /></p>
<p>관리자 페이지 소개라 별로 할 게 없었다. 장고의 강력한 어드민 페이지 짱짱맨</p>
<h2 id="heading-view-template">view 와 template</h2>
<p>3장은 view 와 template 을 다루는 방법에 대해 설명하는 장이다.</p>
<p>MVC 패턴과 같이 동적으로 페이지를 구성해서 리턴하는 방식을 사용하는데, 역시 오래된 프레임워크 답다는 생각을 했다. Django Rest Framework(DRF) 라는 것을 발견했다. Django 자체는 MTV 패턴이라는 MVC 패턴 비스무리한 것을 사용하는데, 현대의 웹사이트는 정적 페이지와 API 서버를 이용해 구성된다. 백엔드 프레임워크로써 Restful API Server 를 구성하기 위해 관련 기능을 모아둔 프레임워크가 있다. 나중에 실제로 프로젝트를 할 때는 Vue.js 와 DRF 를 이용해서 사이트를 구성할 것이기 때문에 template 관련해서는 가볍게 살펴보고 넘어갔다.</p>
<p>결국 이번 장에서 배운 것은 파이썬의 기본 문법과 template 문법이다.</p>
<pre><code class="lang-python"><span class="hljs-function"><span class="hljs-keyword">def</span> <span class="hljs-title">detail</span>(<span class="hljs-params">request, question_id</span>):</span>
    <span class="hljs-keyword">return</span> HttpResponse(<span class="hljs-string">"You're looking at question %s."</span> % question_id)
</code></pre>
<p>위의 예시에서 <code>%</code> 연산자로 숫자나 문자열을 추가할 수 있다는 것을 알게 되었다. javascript 의 탬플릿 리터럴 와 비슷한 기능을 하는 것 같다. (템플릿 리터럴이 더 직관적이고 편한 것 같다)</p>
<p>template 문법은 php 의 그것과 비슷했다. php, ruby on rails, jsp 등에서 동적 웹 구성을 위한 템플릿 문법으로 자주 보아서 크게 이해하기 어렵지는 않았다.</p>
<p>python 에서 문법이 축약된 버전을 보고 원본을 연상하기 어려웠다는 점에서 받아들이기 힘들었다.</p>
<p>4장 역시 view 와 template 관련 내용이 주를 이루었다. ListView, DetailView 같은 generic View 를 이용해서 간단하게 view 를 구성하는 방법이 나왔다. 앞에서 말했다시피 view 에는 크게 관심이 없기 때문에 이런 기능이 있다는 것만 숙지하고 넘어갔다.</p>
]]></content:encoded></item><item><title><![CDATA[일주일동안 장고하기 1일차]]></title><description><![CDATA[💡
express, nest, spring 등 다른 웹 프레임워크를 경험하지 않은 사람은 이해가 안 될 수 있습니다.


장고 튜토리얼 따라하기. 시작하면서 써놓지 않았지만 로컬 기기는 맥북이다. 튜토리얼 따라하는 것이기 때문에 개발환경은 간편하게 venv 를 사용했다.
가상환경 설정 및 장고 세팅
가상환경 설정방법
python3 -m venv ./django-tutorial

가상환경 실행
source django-tutorial/bin/a...]]></description><link>https://jimin52.hashnode.dev/1</link><guid isPermaLink="true">https://jimin52.hashnode.dev/1</guid><dc:creator><![CDATA[Ji-Hyuck, Min]]></dc:creator><pubDate>Tue, 13 Feb 2024 06:36:43 GMT</pubDate><enclosure url="https://cdn.hashnode.com/res/hashnode/image/upload/v1707894958441/ebf69cc8-4f84-4667-9346-89e65ad71274.png" length="0" type="image/jpeg"/><content:encoded><![CDATA[<div data-node-type="callout">
<div data-node-type="callout-emoji">💡</div>
<div data-node-type="callout-text">express, nest, spring 등 다른 웹 프레임워크를 경험하지 않은 사람은 이해가 안 될 수 있습니다.</div>
</div>

<p><a target="_blank" href="https://docs.djangoproject.com/en/5.0/intro/tutorial01/">장고 튜토리얼</a> 따라하기. 시작하면서 써놓지 않았지만 로컬 기기는 맥북이다. 튜토리얼 따라하는 것이기 때문에 개발환경은 간편하게 venv 를 사용했다.</p>
<h2 id="heading-6rca7iob7zmy6rk9ioyepoyglsdrsi8g7j6l6rogioyeuo2mhq">가상환경 설정 및 장고 세팅</h2>
<p>가상환경 설정방법</p>
<pre><code class="lang-bash">python3 -m venv ./django-tutorial
</code></pre>
<p>가상환경 실행</p>
<pre><code class="lang-bash"><span class="hljs-built_in">source</span> django-tutorial/bin/activate
</code></pre>
<p>장고 설치하기</p>
<pre><code class="lang-bash">python -m pip install Django
</code></pre>
<p>장고 설치 확인하기</p>
<pre><code class="lang-bash">python -m django --version
</code></pre>
<p>가상환경 설정, 장고 설치가 잘 된것을 확인했다. 튜토리얼을 따라 쭉 진행하며 어떤 일을 할 수 있는지 파악했다.</p>
<p>장고 프로젝트 생성</p>
<pre><code class="lang-bash">django-admin startproject mysite
</code></pre>
<p><code>mysite</code> 라는 프로젝트가 생성되는 명령어이다.</p>
<h2 id="heading-django-admin-managepy">django-admin 과 manage.py</h2>
<p><code>django-admin</code> 은 NestJs 의 <code>nest</code> 명령어처럼 프레임워크의 기능을 CLI 로 실행할 수 있는 명령어같다. 잠깐 살펴보니 <code>django-admin</code> 에는 기능이 상당히 많은 것 같았다. 역시 프레임워크라 불리는 이유가 있다. node 의 npm 같은 느낌. DB migrate, 데이터베이스 셸, 디버깅 기능, 서버 실행, 테스트 기능들이 내장되어 있다.</p>
<h2 id="heading-6riw67o47zmy6rk9">기본환경</h2>
<p><code>mysite</code> 라는 프로젝트를 생성하면 디렉토리 내부에 기본 파일들이 생성된다.</p>
<pre><code class="lang-plaintext">manage.py
mysite/
    __init__.py
    settings.py
    urls.py
    asgi.py
    wsgi.py
</code></pre>
<p><a target="_blank" href="http://manage.py"><code>manage.py</code></a> 는 <code>django-admin</code> 과 같은 기능을 한다고 한다. <a target="_blank" href="http://manage.py"><code>manage.py</code></a> 는 <code>django-admin</code> 과 같은 동작을 하지만 프로젝트의 <a target="_blank" href="http://settings.py">settings.py</a> 파일의 환경변수를 사용할 수 있다고 써있다. 처음 프로젝트 생성만 하고 이후에는 <a target="_blank" href="http://manage.py"><code>manage.py</code></a> 명령어를 사용하게 된다고 생각하고 넘어갔다. 아래와 같이 사용한다고 한다. 같은 명령어인듯</p>
<pre><code class="lang-bash">$ django-admin &lt;<span class="hljs-built_in">command</span>&gt; [options]
$ manage.py &lt;<span class="hljs-built_in">command</span>&gt; [options]
$ python -m django &lt;<span class="hljs-built_in">command</span>&gt; [options]
</code></pre>
<ul>
<li><p><code>_init__.py</code> 파일은 모듈(파일) 별 import export 를 위한 빈 파일</p>
</li>
<li><p><a target="_blank" href="http://settings.py"><code>settings.py</code></a> 는 Node 의 <code>setting.json</code> 처럼 외부 라이브러리, 명령어, 환경 변수 등 <a target="_blank" href="http://manage.py"><code>manage.py</code></a> 를 사용하기 위한 환경설정 파일.</p>
</li>
<li><p><a target="_blank" href="http://urls.py"><code>urls.py</code></a> 는 Node 의 <code>router</code> 처럼 URL 을 지정해주기 위한 파일</p>
</li>
<li><p><a target="_blank" href="http://asgi.py"><code>asgi.py</code></a> 와 <a target="_blank" href="http://wsgi.py"><code>wsgi.py</code></a> 는 장고의 cgi 모듈이라고 이해하고 넘어갔다. <code>wsgi</code> 는 STDIN 을 이용하</p>
<p>  는 <code>cgi</code> 와는 다르게 object 단위로 전송한다고 하고 <code>asgi</code> 는 비동기 IO 를 지원한다고 한다.</p>
</li>
</ul>
<h2 id="heading-7zse66gc7kcd7yq4ioylpo2wiq">프로젝트 실행</h2>
<p><a target="_blank" href="http://manage.py"><code>manage.py</code></a> 로 서버를 실행할 수 있다.</p>
<pre><code class="lang-bash">python manage.py runserver
</code></pre>
<p>서버를 실행하면 마이그레이션이 안되었다는 경고문이 나오는데,</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1707808190430/391143e8-e469-475f-8689-2d14dc51dc83.png" alt class="image--center mx-auto" /></p>
<p>일단 무시하고 넘어가라는 친절한 튜토리얼 <a target="_blank" href="http://localhost:8000">localhost:8000</a> 으로 접속하면...</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1707530739695/913fedb7-c1af-4dc1-9a35-ce922e9f9e34.png" alt /></p>
<p>잘됐네~ 잘됐어~</p>
<p><code>runserver</code> 명령어에 대한 설명은 <code>django-admin</code> 문서에 자세히 나와있다. 주소나 포트를 변경할 수 있고 이런저런 기능이 있다.</p>
<h2 id="heading-7jwxioy2loqwgo2vmoq4sa">앱 추가하기</h2>
<p>여기서 끝이 아니다~~ 일주일만에 해야해서 튜토리얼 2까지는 해야한다.</p>
<p>polls 라는 설문조사 앱을 추가하는 예제가 나온다. <a target="_blank" href="http://manage.py">manage.py</a> 파일이 있는 곳에서 아래 명령어를 실행하자.</p>
<pre><code class="lang-bash">python manage.py startapp polls
</code></pre>
<p><code>polls/</code> 디렉토리가 생기고 아래와 같이 구성된다.</p>
<pre><code class="lang-plaintext">polls/
    __init__.py
    admin.py
    apps.py
    migrations/
        __init__.py
    models.py
    tests.py
    views.py
</code></pre>
<p>...일단 넘어가자 튜토리얼이 하라는 대로 파일들을 변경하자. <a target="_blank" href="http://views.py"><code>views.py</code></a></p>
<pre><code class="lang-plaintext">```python
from django.http import HttpResponse


def index(request):
    return HttpResponse("Hello, world. You're at the polls index.")
</code></pre>
<p><a target="_blank" href="http://urls.py"><code>urls.py</code></a> 파일이 기본적으로 없는데 생성하고 복붙하자</p>
<pre><code class="lang-python"><span class="hljs-keyword">from</span> django.urls <span class="hljs-keyword">import</span> path

<span class="hljs-keyword">from</span> . <span class="hljs-keyword">import</span> views

urlpatterns = [
    path(<span class="hljs-string">""</span>, views.index, name=<span class="hljs-string">"index"</span>),
]
</code></pre>
<p>그리고 <code>mysite/</code> 내부의 <a target="_blank" href="http://urls.py">urls.py</a> 도 수정해줘야 한다.</p>
<pre><code class="lang-python"><span class="hljs-keyword">from</span> django.contrib <span class="hljs-keyword">import</span> admin
<span class="hljs-keyword">from</span> django.urls <span class="hljs-keyword">import</span> include, path

urlpatterns = [
    path(<span class="hljs-string">"polls/"</span>, include(<span class="hljs-string">"polls.urls"</span>)),
    path(<span class="hljs-string">"admin/"</span>, admin.site.urls),
]
</code></pre>
<p>튜토리얼에서 <a target="_blank" href="http://urls.py"><code>urls.py</code></a> 와 <code>include()</code> 함수가 왜 좋은지 설명한다. <code>include()</code> 함수는 접두어 떼고 넘겨줘서 파싱할 때 편할것 같기는 하다. 찾아보니 DRY 원칙을 url 에 적용한 듯 한데, 복잡한 url 을 다뤄봐야 실감할 수 있을 것 같다. 일단 넘어가자</p>
<pre><code class="lang-bash">python manage.py runserver
</code></pre>
<p>다시 서버를 실행하고 <a target="_blank" href="http://localhost:8000/polls"><code>localhost:8000/polls</code></a> 로 접속하면 아까 복붙했던 polls/views 에 적어둔 메시지가 보인다. 튜토리얼 1장 끝!</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1707808271174/32e48551-f2a0-4bdd-8123-8f71c6538836.png" alt /></p>
<h2 id="heading-database">Database 세팅</h2>
<p>2장 시작! 연결되는 내용이다</p>
<p>드디어 <a target="_blank" href="http://settings.py"><code>settings.py</code></a> 파일을 건드린다. 디폴트로 SQLite 인 게 좋았다. 여러 DB 환경마다 세팅하고 migrate 하는게 은근히 스트레스받다보니 간단하게 튜토리얼하기에는 이만한 DB 가 없는 것같다. 파일로 관리하니 눈에 잘 보이기도 하고. express 유저로써 DB 연결하려면 라이브러리 설치하고 설정파일 만들어서 연동해야 했었는데 세팅파일에서 모두 설정하게 해주니 편하다는 생각이 들었다. 이게 프레임워크지. 약간 검색해보니 설정만 변경하면 RDBMS 간에 migrate 도 간단하다는 것 같다. 직접 해봐야 알겠지만.</p>
<pre><code class="lang-bash">python manage.py migrate
</code></pre>
<p>migrate 를 하면 뭔가 된 것 같다. auth, admin 관련된 기본 DB 정보가 migarte 되었을거라 추정해보고 넘어갔다.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1707808840364/ee95b7f4-ecd9-4d8d-a3a1-0dc8d53d838e.png" alt class="image--center mx-auto" /></p>
<p><code>polls/</code><a target="_blank" href="http://models.py"><code>models.py</code></a> 파일에 아래와 같이 추가하고</p>
<pre><code class="lang-python"><span class="hljs-keyword">from</span> django.db <span class="hljs-keyword">import</span> models


<span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">Question</span>(<span class="hljs-params">models.Model</span>):</span>
    question_text = models.CharField(max_length=<span class="hljs-number">200</span>)
    pub_date = models.DateTimeField(<span class="hljs-string">"date published"</span>)


<span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">Choice</span>(<span class="hljs-params">models.Model</span>):</span>
    question = models.ForeignKey(Question, on_delete=models.CASCADE)
    choice_text = models.CharField(max_length=<span class="hljs-number">200</span>)
    votes = models.IntegerField(default=<span class="hljs-number">0</span>)
</code></pre>
<p><a target="_blank" href="http://settings.py"><code>settings.py</code></a> 에 아래와 같이 추가하면</p>
<pre><code class="lang-python">INSTALLED_APPS = [
    <span class="hljs-string">"polls.apps.PollsConfig"</span>, <span class="hljs-comment"># 이 한줄만 추가하면 된다.</span>
    <span class="hljs-string">"django.contrib.admin"</span>,
    <span class="hljs-string">"django.contrib.auth"</span>,
    <span class="hljs-string">"django.contrib.contenttypes"</span>,
    <span class="hljs-string">"django.contrib.sessions"</span>,
    <span class="hljs-string">"django.contrib.messages"</span>,
    <span class="hljs-string">"django.contrib.staticfiles"</span>,
]
</code></pre>
<h3 id="heading-migration">Migration</h3>
<p>makemigrations 명령어로 뭔가 마이그레이션한다.</p>
<pre><code class="lang-bash">python manage.py makemigrations polls
</code></pre>
<p>실행 결과</p>
<pre><code class="lang-plainText">Migrations for 'polls':
  polls/migrations/0001_initial.py
    - Create model Question
    - Create model Choice
</code></pre>
<p>클래스 만들어서 마이그레이션하는 건 orm 사용할 때 써봤지만 프레임워크 기본 기능으로 제공하니 신기했다.</p>
<pre><code class="lang-plaintext">python manage.py sqlmigrate polls 0001
</code></pre>
<p>이렇게 하면 <code>polls/migration/</code> 디렉토리 안에 migrate 파일도 만들어준다.</p>
<p>튜토리얼 예시에서는 PostgreSQL 로 설정한 예시를 보여주는데 장고 ORM 에서 설정한 데이터 형식으로 저장한 후 데이터베이스마다 알맞은 형식으로 변경해서 제공해주는 것 같았다.</p>
<pre><code class="lang-bash">python manage.py migrate
</code></pre>
<p>이렇게 하면 현재 프로젝트의 migration 파일들을 실행해주는 것 같다.</p>
<h3 id="heading-django-shell">Django shell</h3>
<p>그 다음 어마어마한 기능이 나왔다. 무려 셸을 실행시키는 기능.</p>
<pre><code class="lang-bash">python manage.py shell
</code></pre>
<p>그러면 이런 거 할 수 있구요</p>
<pre><code class="lang-plainText">&gt;&gt;&gt; from polls.models import Choice, Question  # Import the model classes we just wrote.

# No questions are in the system yet.
&gt;&gt;&gt; Question.objects.all()
&lt;QuerySet []&gt;

# Create a new Question.
# Support for time zones is enabled in the default settings file, so
# Django expects a datetime with tzinfo for pub_date. Use timezone.now()
# instead of datetime.datetime.now() and it will do the right thing.
&gt;&gt;&gt; from django.utils import timezone
&gt;&gt;&gt; q = Question(question_text="What's new?", pub_date=timezone.now())

# Save the object into the database. You have to call save() explicitly.
&gt;&gt;&gt; q.save()

# Now it has an ID.
&gt;&gt;&gt; q.id
1
</code></pre>
<p><a target="_blank" href="http://manage.py"><code>manage.py</code></a> 는 신이라서 다 해줍니다.</p>
<p>그 다음 Choice, Question 클래스에 출력함수 추가하고 커스텀 함수 추가하는 일을 하는데 해보고 넘어갔다. 셸에서 DB 에 저장 삭제하는 기능은 테스트코드 작성할 때 유용할 것 같다는 느낌을 받았다.</p>
]]></content:encoded></item><item><title><![CDATA[일주일동안 Django 하기]]></title><description><![CDATA[취업을 준비하는 도중 여러 회사의 공고글을 보았다.
Node.js 신입 개발자 공고가 가뭄에 콩 나듯 하는 현상 때문에 웹 백엔드 공고면 무조건 지원서를 넣기 시작했다.
Node.js 의 ExpressJs 나 NestJs 에 비해서 Django 는 어떤 특징이 있을지 궁금하기도 하고
개발하는 데 있어서 언어나 프레임워크는 중요하지 않다는 이유없는 신념도 있었으며
그래도 Django 개발자를 뽑는데 튜토리얼 정도는 경험해봐야 하지 않을까 하는 마...]]></description><link>https://jimin52.hashnode.dev/django</link><guid isPermaLink="true">https://jimin52.hashnode.dev/django</guid><category><![CDATA[one week]]></category><category><![CDATA[Django]]></category><category><![CDATA[portfolio]]></category><category><![CDATA[Tutorial]]></category><dc:creator><![CDATA[Ji-Hyuck, Min]]></dc:creator><pubDate>Fri, 09 Feb 2024 10:07:18 GMT</pubDate><enclosure url="https://cdn.hashnode.com/res/hashnode/image/stock/unsplash/ylveRpZ8L1s/upload/ac326fd8b44bf71695a9e9d636a57ea6.jpeg" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p>취업을 준비하는 도중 여러 회사의 공고글을 보았다.</p>
<p>Node.js 신입 개발자 공고가 가뭄에 콩 나듯 하는 현상 때문에 웹 백엔드 공고면 무조건 지원서를 넣기 시작했다.</p>
<p>Node.js 의 ExpressJs 나 NestJs 에 비해서 Django 는 어떤 특징이 있을지 궁금하기도 하고</p>
<p>개발하는 데 있어서 언어나 프레임워크는 중요하지 않다는 이유없는 신념도 있었으며</p>
<p>그래도 Django 개발자를 뽑는데 튜토리얼 정도는 경험해봐야 하지 않을까 하는 마음에</p>
<p>설을 맞이해서 1주일 동안 한 번도 경험해보지 못했던 Django 에 대해 학습을 해보기로 했다.</p>
<p>3일 정도 간단하게 <a target="_blank" href="https://docs.djangoproject.com/en/5.0/intro/tutorial01/">공식 튜토리얼</a>을 따라가며 기능을 알아보고</p>
<p>3일 정도는 사이드 프로젝트로 하고자 하는 Todo API 서버를 만들어보도록 할 것이다.</p>
<p>하루는 마진.. ㅎ..</p>
<p>사실 포트폴리오로 사용할 것이기 때문에 블로그 포스팅이 더 중요하다.</p>
<p>시작해보자</p>
]]></content:encoded></item></channel></rss>