<?xml version="1.0" encoding="utf-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom">
    <channel>
        <title>django_apps.log</title>
        <link>https://velog.io/</link>
        <description>django developer</description>
        <lastBuildDate>Sun, 14 Nov 2021 02:59:30 GMT</lastBuildDate>
        <docs>https://validator.w3.org/feed/docs/rss2.html</docs>
        <generator>https://github.com/jpmonette/feed</generator>
        <image>
            <title>django_apps.log</title>
            <url>https://images.velog.io/images/django_apps/profile/c53af07b-50df-4307-9f53-cb6e748608ee/django.png</url>
            <link>https://velog.io/</link>
        </image>
        <copyright>Copyright (C) 2019. django_apps.log. All rights reserved.</copyright>
        <atom:link href="https://v2.velog.io/rss/django_apps" rel="self" type="application/rss+xml"/>
        <item>
            <title><![CDATA[[보충] Django를 사용하기 전에 고려해야 할 것 (2)]]></title>
            <link>https://velog.io/@django_apps/%EB%B3%B4%EC%B6%A9-Django%EB%A5%BC-%EC%82%AC%EC%9A%A9%ED%95%98%EA%B8%B0-%EC%A0%84%EC%97%90-%EA%B3%A0%EB%A0%A4%ED%95%B4%EC%95%BC-%ED%95%A0-%EA%B2%83-2</link>
            <guid>https://velog.io/@django_apps/%EB%B3%B4%EC%B6%A9-Django%EB%A5%BC-%EC%82%AC%EC%9A%A9%ED%95%98%EA%B8%B0-%EC%A0%84%EC%97%90-%EA%B3%A0%EB%A0%A4%ED%95%B4%EC%95%BC-%ED%95%A0-%EA%B2%83-2</guid>
            <pubDate>Sun, 14 Nov 2021 02:59:30 GMT</pubDate>
            <description><![CDATA[<p>[보충] Django를 사용하기 전에 고려해야 할 것 (2)</p>
]]></description>
        </item>
        <item>
            <title><![CDATA[[보충] Django를 사용하기 전에 고려해야 할 것]]></title>
            <link>https://velog.io/@django_apps/Series03-2</link>
            <guid>https://velog.io/@django_apps/Series03-2</guid>
            <pubDate>Fri, 12 Nov 2021 00:03:06 GMT</pubDate>
            <description><![CDATA[<blockquote>
<h3 id="background">Background</h3>
</blockquote>
<p>이번 포스팅에서는 아래의 질문으로 시작하려 한다.</p>
<blockquote>
<p>여러분은 왜 <code>django</code> 를 사용하는가?</p>
</blockquote>
<p>아마 대부분은...</p>
<pre><code class="language-bash">1. `python` 으로 웹 애플리케이션을 만들 수 있기 때문에 
2. `Zero Base`에서 개발하는데에 큰 시간이 안 들기 때문에
3. 주변 동종업계에서 많이 채용하여 쓰고 있기 때문에
4. 업무 환경상 정해진 스펙이였기 때문에</code></pre>
<p>위와 같은 이유가 아니였을까 싶다.</p>
<p>하지만 이번 포스팅에서는 아래 질문에 집중해보려 한다.</p>
<p><code>django</code> 를 이용해서 어디까지 커버할 것 인지가 정해져야, 구체적인 프로젝트 기술 스펙과 <code>Tier</code> 구조가 명확해 지기 때문이다.</p>
<blockquote>
<p><code>django</code>로 어느 부분까지 개발할 것인지</p>
</blockquote>
<p>혹시 위 질문에 대해서 아래처럼 대답하려 했다면, <code>django</code> 가 당신의 프로젝트에서 어떤 부분을 담당하게 되는지가 상당히 막연한 상황이 될 것이다. </p>
<pre><code>서버는 django 를 이용해서 개발한다.</code></pre><blockquote>
<h3 id="당신의-업무에서-django의-역할을-정해라">당신의 업무에서 Django의 역할을 정해라</h3>
</blockquote>
<p><code>django</code> 로 할 수 있는 개발영역은 대략 아래와 같다.</p>
<ol>
<li>서버 (<code>back-end</code>) 로직 : 컨트롤러(<code>View</code>) + 모델(<code>DB</code>)</li>
<li>서버 (<code>back-end</code>) 로직 + 프론트 엔드 페이지 &gt; (<code>fullstack</code>) : 템플릿(<code>Template</code>) + <code>α Packages</code> (필요에 따라)</li>
<li>RESTful API 서버</li>
</ol>
<p>즉, 사용자의 <code>Use case</code> 에 따라서, 서버, 서버/프론트 개발을 아우르는 <code>fullstack</code> 프레임워크로 활용할 수도 있고 <code>API</code> 전용 서버로 개발할 수도 있다.</p>
<p>어디까지 활용할 것인지에 대해서는 특별히 정답은 없다.</p>
<p>프로젝트의 시스템 구조, 개발인력, 데이터 구조 등 각각 처한 상황에 맞춰서 유연하게 사용하면 된다.</p>
<p>다만, <code>django</code> 사용을 고려하기에 앞서서 아래 3가지에 대한 답을 내보도록 하자.</p>
<pre><code class="language-bash">1. django로 할수 있는 개발영역과 현재 업무의 개발사양 / 시스템 구조는 무엇인가?
2. 다른 웹 프레임워크 보다 django를 쓰면 좋은점과 나쁜점은 무엇인가?
3. django를 어디까지 사용할 것인가? 서버만? 서버 + 프론트 둘다? + API 서버로만 활용?</code></pre>
<p>당신의 결정에 의해서 대략적인 프로젝트 구조의 이미지가 그려질 것이다.</p>
<p>아래와 같이예를 들어보자</p>
<p><code>서버 + 프론트 둘다 django를 이용하여 개발한다</code></p>
<p>위와 같은 사양으로 간다고 하면 당신은 따로 <code>front-end</code> 개발을 할 필요가 없어지는 대신에, <code>django</code> 프로젝트 안에 <code>template</code> 를 작성해야 할 것이고, <code>page reloading</code> 이 페이지별로 요쳥 할 때마다 불려지기 떄문에 성능이 살짝 느려질 수도 있다.</p>
<blockquote>
<p>성능은 무조건 빠르게 하고싶다면?</p>
</blockquote>
<p>만약 성능이 최고 우선순위라면, <code>django</code> 로는 서버로직만 맡고
<code>front-end</code> 로는 <code>SPA</code> 프레임워크로 결정하는게 나은지 검토해봐야 할 것이다.</p>
<p>이런식으로 <code>django</code> 의 활용 범위를 사용하기 전에 확실히 정한다면, 전체적인 프로젝트 시스템 아키텍쳐가 그려지고, 앞으로 개발을 위해 공부/조사해야 할 것들, 필요한 외부 <code>packages</code>, TODO 리스트 등이 훨씬 명확해 질 것이다.</p>
<p>다음 포스팅에서는 <code>django</code> 에 빠질 수 없는 라이브러리인 <code>rest framework</code> 에 대해서 알아보겠다.</p>
<p><img src="https://images.velog.io/images/django_apps/post/d4460915-b281-4a7d-b6c2-85f7b7e2490c/4169387-middle.png" alt=""></p>
<p>Thank you!</p>
]]></description>
        </item>
        <item>
            <title><![CDATA[[Django For Beginners] C3. Pages App (1)]]></title>
            <link>https://velog.io/@django_apps/Series02-4</link>
            <guid>https://velog.io/@django_apps/Series02-4</guid>
            <pubDate>Thu, 11 Nov 2021 02:37:36 GMT</pubDate>
            <description><![CDATA[<blockquote>
<h3 id="chapter-3-pages-app">Chapter 3: Pages App</h3>
</blockquote>
<p>오늘 포스팅에서는, 새로운 <code>django App</code> 을 개발해볼 것이다.</p>
<p>특히 <code>Template</code> 을 확장시켜서 저번에 만들었던 <code>Hello World App</code> 보다 그럴 듯한 페이지를 만들어보자.</p>
<blockquote>
<p>프로젝트 생성 및 기본 환경 설정 하기</p>
</blockquote>
<p>가상 <code>python</code> 환경에 들어가서, 새로운 <code>project</code> 와 <code>app</code> 을 만든다.</p>
<p><code>source venv/bin/activate</code></p>
<p><code>django-admin startproject config2</code></p>
<p><img src="https://images.velog.io/images/django_apps/post/df5811b0-2c2b-4d3f-8651-331f009aabdb/Screen%20Shot%202021-11-11%20at%2011.26.01.png" alt=""></p>
<p><code>cd config2</code></p>
<p><code>python manage.py startapp pages</code></p>
<p><img src="https://images.velog.io/images/django_apps/post/b509cadc-8f64-4030-80a8-c9d580e0b9af/Screen%20Shot%202021-11-11%20at%2011.27.49.png" alt=""></p>
<p>그리고, <code>config2</code> 프로젝트 폴더의 <code>settings.py</code> 에서 우리가 추가한 <code>pages App</code> 을 추가하자.</p>
<pre><code class="language-python"># Application definition

INSTALLED_APPS = [
    &#39;django.contrib.admin&#39;,
    &#39;django.contrib.auth&#39;,
    &#39;django.contrib.contenttypes&#39;,
    &#39;django.contrib.sessions&#39;,
    &#39;django.contrib.messages&#39;,
    &#39;django.contrib.staticfiles&#39;,

    &#39;pages&#39;, #new App
]</code></pre>
<p>마지막으로 기본 DB link 작업을 위해,
<code>migrate</code> 명령을 실행하자.</p>
<p><code>python manage.py migrate</code></p>
<p><img src="https://images.velog.io/images/django_apps/post/f481ee1d-31f8-47fa-b540-b48873cf35a5/Screen%20Shot%202021-11-11%20at%2011.33.36.png" alt=""></p>
<p>이것으로 기본적인 환경 세팅은 끝났다.
서버를 가동하고 기본 페이지가 잘 표시되는지 확인해 보자.</p>
<p><code>python manage.py runserver</code></p>
<p><img src="https://images.velog.io/images/django_apps/post/6ffeade3-276d-4635-b35c-ef7f070db87e/Screen%20Shot%202021-11-11%20at%2011.34.43.png" alt=""></p>
<p>마이그레이션이 완료되었으면, 웹브라우저로 아래에 접속해보자.</p>
<p><code>http://127.0.0.1:8000/</code></p>
<p><img src="https://images.velog.io/images/django_apps/post/d9e913f5-77e1-4d1e-a3e7-7e4f70d47aaf/Screen%20Shot%202021-11-11%20at%2011.34.55.png" alt=""></p>
<p>화면이 잘 표시된다.
이것으로 기본 세팅은 완료되었다.</p>
<p>다음 포스팅에서는 본격적으로 <code>Template</code> 을 작성해보고, <code>View</code> 파일과 연계하는 법에 대하여 알아보자.</p>
<p>Thank you!</p>
]]></description>
        </item>
        <item>
            <title><![CDATA[[Django For Beginners] C2. Hello World App (3)]]></title>
            <link>https://velog.io/@django_apps/Series02-3</link>
            <guid>https://velog.io/@django_apps/Series02-3</guid>
            <pubDate>Mon, 08 Nov 2021 02:48:47 GMT</pubDate>
            <description><![CDATA[<blockquote>
<h3 id="chapter-2-hello-world-app-3">Chapter 2. Hello World App (3)</h3>
</blockquote>
<p>저번 포스팅에서는 <code>App</code> 을 <code>Project</code> 안에 만들어보았다.</p>
<p>이번 포스팅에서는 <code>View</code> 를 하나 만들어서, 우리가 요청하는 <code>url</code>에 응답하도록 해보자.</p>
<blockquote>
<p>View 만들기</p>
</blockquote>
<p>우리가 특정한 <code>url</code>로 <code>request</code>를 할때 반응시키기 위하여, <code>View</code>를 만들어보도록 한다.</p>
<p><code>pages/views.py</code> 파일을 열어서 다음과 같이 작성한다.</p>
<pre><code class="language-python"># page/views.py
from django.http import HttpResponse

# Create your views here.
def homePageView(request):
  return HttpResponse(&#39;Hello, World!&#39;)</code></pre>
<p>구조는 간단하다. </p>
<p><code>front-end</code> 에 응답을 주기 위하여, <code>HttpResponse</code> 클래스를 <code>import</code> 하고, <code>homePageView</code> 라는 이름의 함수를 정의한다.</p>
<p>간단히 설명하자면, 특정한 요청이 들어올 때 <code>views.py</code> 파일에 정의되어있는 특정 메소드를 호출하여 처리하는 식이다.</p>
<p>외부 요청에 의해 <code>homePageView</code> 메소드가 불렸을 때, 우리는 단순히 <code>front-end</code> 에 <code>Hello, World!</code> 라는 문자열을 돌려주는 처리를 하게 된다.</p>
<p>다음으로, 외부 요청과 <code>homePageView</code> 를 연결하기 위한 <code>url</code> 라우팅 설정을 하도록 하자.</p>
<blockquote>
<p>url routing 설정하기</p>
</blockquote>
<p>우리는 <code>pages App</code> 전용 <code>url</code> 설정을 분리해서 처리할 것이다. 유지보수도 쉽고, <code>App</code> 별로 분리가 가능하기 때문이다.</p>
<p>아래 경로에 <code>urls</code> 파일을 하나 만들자.</p>
<p><code>config/pages/urls.py</code></p>
<p>아래와 같이 우리가 만들었던 <code>View</code>를 추가하자.</p>
<pre><code class="language-python">from django.urls import path
from .views import homePageView

urlpatterns = [
    path(&#39;&#39;, homePageView, name=&#39;home&#39;)
]</code></pre>
<p>이것으로 끝이 아니다. 실제 <code>root url</code> 파일에 <code>import</code> 시켜야 한다.</p>
<p><code>config/urls.py</code></p>
<pre><code class="language-python">from django.contrib import admin
from django.urls import path, include

urlpatterns = [
    path(&#39;admin/&#39;, admin.site.urls),
    path(&#39;&#39;, include(&#39;pages.urls&#39;)),
]</code></pre>
<p>이것으로 개발작업은 끝이다.</p>
<p>서버를 가동하고, <code>root url</code> -&gt; <code>http://127.0.0.1:8000/</code> 로 접근해보자.</p>
<p><code>python manage.py runserver</code></p>
<p><img src="https://images.velog.io/images/django_apps/post/7928e654-220f-488f-93f6-2cd444eab2e2/Screen%20Shot%202021-11-08%20at%2011.46.40.png" alt=""></p>
<p>아래와 같이 <code>Hello, World!</code> 문자열이 출력되는 것을 알 수 있다.</p>
<p><img src="https://images.velog.io/images/django_apps/post/6617118a-3d60-40be-970c-21a1cde65311/Screen%20Shot%202021-11-08%20at%2011.47.03.png" alt=""></p>
<p>이것으로 간단히 뷰와 라우팅을 설정하여 실제로 원하는 문자열을 <code>front-end</code> 로 응답하여 보았다.</p>
<p>다음은 조금 더 관련내용을 자세하게 살펴보도록 하자.</p>
]]></description>
        </item>
        <item>
            <title><![CDATA[[Django For Beginners] C2. Hello World App (2)]]></title>
            <link>https://velog.io/@django_apps/Series2-02</link>
            <guid>https://velog.io/@django_apps/Series2-02</guid>
            <pubDate>Sun, 07 Nov 2021 02:43:15 GMT</pubDate>
            <description><![CDATA[<blockquote>
<h3 id="chapter-2-hello-world-app-2">Chapter 2. Hello World App (2)</h3>
</blockquote>
<p>전 포스팅에 이어서, <code>config</code> 프로젝트 아래에 <code>App</code> 을 하나 생성해보려 한다.</p>
<p><code>django</code> 는 코드를 깔끔하고 읽기 쉽게 끔 하기 위해서 <code>Project</code> 와 <code>App</code> 의 컨셉을 사용한다.</p>
<p><code>django</code> 는 1개의 <code>Project</code> 마다 다수의 <code>App</code> 을 가질 수 있으며 각각의 기능별로 분리하는 로직을 가짐으로써 보다 체계적인 프로젝트 관리가 가능하게끔 한다.</p>
<p>한가지 예를 들어보자.</p>
<p>어떤 e-commerce 사이트를 개발한다고 했을 때, <code>e-commerce</code> 프로젝트를 하나 만든 후에, 그 아래에 기능별로 여러가지 <code>App</code>을 생성하는 식이다.</p>
<p><code>Project</code> -&gt; e-commerce
<code>App</code> -&gt; user_authentication (회원 인증), payments (구매), listing (조회) </p>
<p>그럼 바로 <code>pages</code> 라는 이름의 <code>App</code> 을 만들어 보자.</p>
<p><code>python manage.py startapp pages</code></p>
<p><img src="https://images.velog.io/images/django_apps/post/b178bcb5-3005-4987-8d1f-ade9ab7cb805/Screen%20Shot%202021-11-07%20at%2011.31.34.png" alt=""></p>
<p><code>pages</code> 폴더가 만들어졌다.
구조를 확인해보자.</p>
<p><code>tree</code></p>
<p><img src="https://images.velog.io/images/django_apps/post/b5538a55-8d8a-4e09-8d45-ae3967eca722/Screen%20Shot%202021-11-07%20at%2011.34.08.png" alt=""></p>
<p>간단히 각각의 폴더 / 파일에 대해서 설명하자면 아래와 같다.</p>
<ul>
<li>admin.py : <code>django</code> 가 기본으로 제공해주는 <code>Admin App</code></li>
<li>apps.py : <code>App</code> 환경설정 파일</li>
<li>migrations/ : <code>models.py</code> 에서 변경점을 기록하여 실제 <code>DB</code> 에 반영하기 위한 파일</li>
<li>models.py : <code>DB</code> 모델을 정의 하는 파일, 이 파일을 참고하여 <code>django</code> 는 내부 <code>Model</code>과 <code>DB</code> 를 링크시킨다</li>
<li>tests.py : <code>App</code> 단위의 테스트 파일</li>
<li>views.py : Web browser / API 와 연동하여 <code>Response</code> / <code>Request</code> 로직을 작성하는 파일</li>
</ul>
<p>이번 포스팅에서는 <code>App</code>의 개념과 구조에 대해서 간단히 알아보았다.</p>
<p>다음 포스팅에서는 실제로 <code>App</code> 아래에서 <code>View</code>를 만들어서, 특정한 <code>url</code>로 요청이 들어왔을 떄 웹브라우저에 원하는 문자를 출력시켜 보도록 하자.</p>
<p>Thank you!</p>
]]></description>
        </item>
        <item>
            <title><![CDATA[[Django For Beginners] C2. Hello World App (1) ]]></title>
            <link>https://velog.io/@django_apps/Series2-01</link>
            <guid>https://velog.io/@django_apps/Series2-01</guid>
            <pubDate>Sat, 06 Nov 2021 02:51:37 GMT</pubDate>
            <description><![CDATA[<blockquote>
<h3 id="django-for-beginners-공부를-시작하면서">Django For Beginners 공부를 시작하면서...</h3>
</blockquote>
<p>이번 시리즈는 <code>William S. Vincent</code> 가 집필한 <code>Django For Beginners</code> 를 참고하여 첫 예제부터 차근차근 공부해 나가보려 한다.</p>
<p>기획 의도로는 여러가지 실전 예제를 개발해나가면서 다양한 상황에서 필요한 <code>Django</code> 스킬과 개념을 <code>초보자</code> 관점에서 쉽게 풀어내고 있기 때문이다.</p>
<p>또, 이론과 개념/구조 위주로만 기술하고 있는 기존의 레퍼런스 보다는 직접 결과물을 볼 수 있으니 보람도 있고, 실제로 실무적인 <code>context</code>에 필요한 <code>Django</code>의 다양한 라이브러리 / 기능의 사용법, 확장하는 법을 경험할 수 있기에 필자로서도 이를 여러분께 공유하는 것도 여러모로 도움이 될 것 같아서이다.</p>
<p>그럼 <code>Chapter 2: Hello World App</code> 부터 시작해보자!</p>
<blockquote>
<p>Chapter 2: Hello World App</p>
</blockquote>
<p>자, 시작하기에 앞서서 작업할 폴더를 생성하고 <code>python</code> 가상환경을 링크 시킨뒤에 <code>django</code> 를 설치하자.</p>
<p><code>terminal</code> 에 들어가서, 작업하고 싶은 폴더에 들어간다.
그리고 가상환경을 <code>venv</code> 폴더안에 구축하기 위해서 아래 커맨드로 만들어준다.</p>
<p><code>python3 -m venv venv</code></p>
<p><img src="https://images.velog.io/images/django_apps/post/630e9752-8dd2-4f17-a1af-fd964e613559/Screen%20Shot%202021-11-06%20at%2010.33.27.png" alt=""></p>
<p><code>venv</code> 폴더 안에 가상환경 파일이 만들어졌다.
이제 방금 만든 가상환경 모드로 아래 커맨드를 실행해서 세팅해보자.</p>
<pre><code>source venv/bin/activate</code></pre><p><img src="https://images.velog.io/images/django_apps/post/015bf0ea-c0c1-4c90-8f62-5fa720693e0f/Screen%20Shot%202021-11-06%20at%2010.37.02.png" alt=""></p>
<p>위의 스크린샷에서 보이듯이 왼쪽에 <code>(venv)</code> 현재세팅되어있는 가상환경폴더명이 보이고 있음을 확인 할 수 있다.</p>
<p>세팅이 완료되었으니, 가상환경안에서 우리가 작업에 필요한 다양한 라이브러리를 설치하면 된다.</p>
<p>덧붙여서, 우리가 현재 들어와있는 가상환경은 이번에 개발할 <code>Hello World App</code> 프로젝트만을 위한, 완전히 독립적인 환경이기 때문에 곧 설치할 라이브러리 버전에 의한 호환성 문제가 다른 프로젝트를 개발할때 생긴다던지의 문제는 일어나지 않으니 안심하고 진행해도 된다.</p>
<p>이제 아래 커맨드로 <code>django</code> 를 설치해보자.</p>
<p>본 도서가 집필되었을 당시에는 <code>3.1.0</code> 버전 기준이였으니 적어도 그 이상은 되야 한다.</p>
<p><code>pip install django~=3.1.0</code></p>
<p><img src="https://images.velog.io/images/django_apps/post/c0da5b70-8a34-4a59-95a8-9185464a3ae5/Screen%20Shot%202021-11-06%20at%2010.50.11.png" alt=""></p>
<p><code>django</code> 가 설치되었으므로, 프로젝트를 아래 커맨드로 하나 만들자.</p>
<p><code>django-admin startproject config</code></p>
<p><img src="https://images.velog.io/images/django_apps/post/adaf8973-535d-4176-95c0-190a7a8f8399/Screen%20Shot%202021-11-06%20at%2011.17.21.png" alt=""></p>
<p>위 처럼 <code>config</code> 이름의 프로젝트가 생성되었다.
프로젝트의 폴더 구조를 아래 커맨드로 확인해보자.</p>
<p><code>tree</code></p>
<p><code>tree</code> 라이브러리가 필요하기 때문에, 설치가 되어있지 않다면 아래 커맨드로 설치한후에 다시 실행하자.</p>
<p><code>brew install tree</code></p>
<p><img src="https://images.velog.io/images/django_apps/post/a7ef2d57-ac3a-4e59-8f52-f0d276082bec/Screen%20Shot%202021-11-06%20at%2011.23.57.png" alt=""></p>
<p>각각의 파일의 용도에 대해 간단히 설명하면 아래와 같다.</p>
<ul>
<li><p>settings.py
프로젝트의 전체적인 시스템을 설정한다. (DB, Template 설정 등)</p>
</li>
<li><p>urls.py
웹 브라우저나, URL Request가 들어오면 어떤 <code>View</code> 로 라우팅 해줄 것 인지를 설정한다.</p>
</li>
<li><p>wsgi.py
외부에서 이벤트 처리가 필요할 경우에 로직을 작성한다.</p>
</li>
<li><p>manage.py
<code>Django</code> 에서 제공해주는 여러가지 편리한 커맨드를 사용할 수 있다.  (server 실행, db 접근, migration 등)</p>
</li>
<li><p>asgi.py
<code>Django 3.0</code> 버전부터 새롭게 추가된 기능으로, 비동기로 처리해야할 작업이 있을 때 작성한다.</p>
</li>
</ul>
<p>자, 이제 <code>Django</code> 프로젝트를 새롭게 만든 후에 자동으로 작성된 <code>DB Model</code> 에 대해서 <code>Migration</code> 을 실행하자. 실제 물리 DB와 매핑하는 과정이다.</p>
<p>아래 커맨드를 실행한다.</p>
<p><code>python manage.py migrate</code></p>
<p><img src="https://images.velog.io/images/django_apps/post/2cf28a4c-c58a-4c8c-8143-24114435e9c1/Screen%20Shot%202021-11-06%20at%2011.41.46.png" alt=""></p>
<p>기본적으로 필요한 DB 매핑 작업이 완료되었다.</p>
<p>이제 서버를 실행시키는데 최소한의 작업이 끝났으니, 아래 커맨드로 서버를 가동시켜보자.</p>
<p><code>python manage.py runserver</code></p>
<p><img src="https://images.velog.io/images/django_apps/post/3bf39a27-e642-4939-8f53-66d04b0dbdd6/Screen%20Shot%202021-11-06%20at%2011.44.23.png" alt=""></p>
<p>에러 없이 실행이 완료되었다.</p>
<p>마지막으로 아래 url에 접속하여 보자.</p>
<p><code>http://127.0.0.1:8000/</code></p>
<p>아래 처럼 페이지가 표시되었다면 작업하기 위한 기본 환경설정은 끝난 것이다.
다음 포스팅에서는 새로운 페이지를 추가하여 우리가 원하는 내용을 웹 페이지에 표시해 보도록 하겠다.</p>
<p><img src="https://images.velog.io/images/django_apps/post/8809b60b-861c-49da-b07e-87893411357e/Screen%20Shot%202021-11-06%20at%2011.48.38.png" alt=""></p>
<p>Thank you!</p>
]]></description>
        </item>
        <item>
            <title><![CDATA[[Series1. DashBoard 만들기] - 17. 페이지 권한 설정]]></title>
            <link>https://velog.io/@django_apps/Series1-17</link>
            <guid>https://velog.io/@django_apps/Series1-17</guid>
            <pubDate>Fri, 05 Nov 2021 02:59:37 GMT</pubDate>
            <description><![CDATA[<blockquote>
<h3 id="권한-설정-해보기">권한 설정 해보기</h3>
</blockquote>
<p>이번 포스팅에서는 로그인 한 유저만 페이지 및 데이터를 표시하게 끔 해보자.</p>
<p>이를 위해서는 권한을 체크하는 로직이 필요한데, <code>rest framework</code> 에서는 <code>permissions</code> 이라는 패키지를 따로 제공하고 있다.</p>
<p>권한 설정을 하고 싶은 <code>View</code> 파일로 들어가서 아래(<code>## 권한설정 추가부분 ##</code>)와 같이 추가해준다.
아래의 예는 <code>Post</code> 데이터를 보여주는 <code>PostViewSet</code> 에서 설정하였다.</p>
<p>ex) <code>view</code> 파일 위치
<code>/dashboard/dashboard_core/views.py</code></p>
<pre><code class="language-python">from rest_framework.permissions import IsAuthenticatedOrReadOnly
.
.
.
# Create your views here.
class PostViewSet(ModelViewSet):
  queryset = Post.objects.all()
  serializer_class = PostSerializer
  ## 권한설정 추가부분 ##
  permission_classes = [IsAuthenticatedOrReadOnly]
  ## 권한설정 추가부분 ##</code></pre>
<p>우리가 추가한 부분은 아래 한 줄인데, 해당하는 <code>View</code> 클래스에 적용하고 싶은 권한 로직이 구현되어 있는 클래스를 <code>permission_classes</code> 정의변수에 assign 한다.</p>
<pre><code class="language-python">permission_classes = [IsAuthenticatedOrReadOnly]</code></pre>
<p>참고로 <code>IsAuthenticatedOrReadOnly</code> 는 이미 <code>rest_framework.permissions</code> 라이브러리에서 제공하는 권한로직들중 하나이다.</p>
<p>당연히, <code>Overriding</code> 도 가능하니 원하는 대로 커스터마이징 해서 쓰면 된다.
필자의 경우에는 <code>GET</code> 요청일 때도 로그인 한 유저만 보이도록 변경하였다.</p>
<p>변경파일: <code>/venv/lib/python3.8/site-packages/rest_framework/permissions.py</code></p>
<pre><code class="language-python">SAFE_METHODS = (&#39;HEAD&#39;, &#39;OPTIONS&#39;)
.
.
.
.
class IsAuthenticatedOrReadOnly(BasePermission):
    &quot;&quot;&quot;
    The request is authenticated as a user, or is a read-only request.
    &quot;&quot;&quot;

    def has_permission(self, request, view):
        return bool(
            request.method in SAFE_METHODS or
            request.user and
            request.user.is_authenticated
        )</code></pre>
<p>이제, 서버를 가동시켜서 로그인 하지 않은 경우와 로그인 한 경우에 각각, <code>posts</code> 데이터를 조회 (<code>GET</code>요청) 해보자.</p>
<p>확인 url: <code>http://127.0.0.1:8000/posts/</code></p>
<blockquote>
<p>로그인 하지 않은 경우</p>
</blockquote>
<p>아래 처럼 권한에러(<code>HTTP RESPONSE CODE -&gt; 403</code>) 가 발생하면서 데이터 로드에 실패했음을 알 수 있다.</p>
<p><img src="https://images.velog.io/images/django_apps/post/2df83e60-30f0-4982-84eb-b70a7bb5ff9b/Screen%20Shot%202021-11-05%20at%2012.09.45.png" alt=""></p>
<blockquote>
<p>로그인을 한 경우</p>
</blockquote>
<p>아래 처럼 정상처리(<code>HTTP RESPONSE CODE -&gt; 200</code>) 된 데이터를 볼 수 있다.</p>
<p><img src="https://images.velog.io/images/django_apps/post/c76ebc5e-88bd-4644-9265-60174e4bc6e4/Screen%20Shot%202021-11-05%20at%2012.10.06.png" alt=""></p>
<p>이것으로 간단히 <code>View</code> 로직에 권한 설정을 하는 방법을 알아보았다.</p>
<p>Thank you!</p>
]]></description>
        </item>
        <item>
            <title><![CDATA[[Series1. DashBoard 만들기] - 16. 로그인 해보기]]></title>
            <link>https://velog.io/@django_apps/Series1-16</link>
            <guid>https://velog.io/@django_apps/Series1-16</guid>
            <pubDate>Tue, 02 Nov 2021 01:52:19 GMT</pubDate>
            <description><![CDATA[<blockquote>
<h3 id="로그인-기능-만들어-보기">로그인 기능 만들어 보기</h3>
</blockquote>
<p>오늘 포스팅에서는 <code>PostUser</code> Model의 <code>username</code> , <code>password</code> 데이터로 로그인 하는 기능을 만들어 보자.</p>
<p><code>django</code>는 기본적으로 로그인 시에, 회원인지 인증하는 처리를 제공해주고 있다.
오늘은 <code>django</code>가 제공하는 인증기능을 이용하여 로그인 기능을 만들어 보도록 하자.</p>
<p>그러나 사실은 이미 로그인 페이지는 존재한다. 저번 포스팅에서 <code>restframework</code>에서 기본적으로 제공해주는 패키지가 있기 때문이다. </p>
<p>서버를 실행하고, 아래 URL에 접속해보자.</p>
<pre><code>python manage.py runserver</code></pre><blockquote>
<p><a href="http://127.0.0.1:8000/api-auth/login">http://127.0.0.1:8000/api-auth/login</a></p>
</blockquote>
<p><img src="https://images.velog.io/images/django_apps/post/85157040-ca60-4372-993e-116320fe1d0b/Screen%20Shot%202021-11-02%20at%2010.28.08.png" alt=""></p>
<p>위 페이지로 정상적으로 로그인은 가능하다.</p>
<p>그러나, 직접 템플릿을 만들어서 자기가 원하는 로그인 화면을 구성할 수도 있다.</p>
<p>아래 경로에 <code>login.html</code> 을 만들고 아래와 같이 작성한다.</p>
<pre><code>dashboard/templates/registration/login.html</code></pre><pre><code class="language-html">{% extends &#39;auth_layout.html&#39; %}
{% load crispy_forms_tags %}
{% block content %}
&lt;h1&gt;Login&lt;/h1&gt;
&lt;div class=&quot;login-form-container&quot;&gt;
  &lt;form method=&quot;POST&quot;&gt;
    {% csrf_token %} {{ form|crispy }}
    &lt;button type=&quot;submit&quot; class=&quot;btn btn-sm btn-outline-primary&quot;&gt;Login&lt;/button&gt;
  &lt;/form&gt;
&lt;/div&gt;
{% endblock %}</code></pre>
<p>그리고 <code>urls.py</code> 파일에, <code>accounts/</code> 경로를 임의로 추가해주고
<code>django.contrib.auth.urls</code> 라우팅 설정을 매핑해주자.</p>
<p>그 뒤는 <code>django</code> 가 알아서 <code>templates</code> 파일을 로드해준다.</p>
<pre><code class="language-python">from django.contrib import admin
from django.urls import include, path

from django_registration.backends.one_step.views import RegistrationView
from dashboard_core.forms import PostUserForm

from rest_framework.routers import DefaultRouter
from dashboard_core.views import PostViewSet, PostUserViewSet

router = DefaultRouter()
router.register(r&quot;posts&quot;, PostViewSet, basename=&quot;post_status&quot;)
router.register(r&quot;users&quot;, PostUserViewSet, basename=&quot;user_status&quot;)

urlpatterns = [
....
    path(&#39;accounts/&#39;, include(&#39;django.contrib.auth.urls&#39;)),
....
]</code></pre>
<p>이제 준비는 끝났다.</p>
<p>아래 스크린 샷에서 12번째 경로로 들어가 보자.</p>
<pre><code>http://127.0.0.1:8000/accounts/login/</code></pre><p><img src="https://images.velog.io/images/django_apps/post/88647a78-f39f-4873-8d47-2fe061631129/Screen%20Shot%202021-11-02%20at%209.57.07.png" alt=""></p>
<p>그럼 아래와 같이 <code>templates</code> 안에 작성했던 로그인 <code>html</code> 파일이 렌더링 된다.</p>
<p><img src="https://images.velog.io/images/django_apps/post/90be0461-dfb7-4f43-91ad-50b78548adf8/Screen%20Shot%202021-11-02%20at%2010.49.16.png" alt=""></p>
<p>정상적으로 로그인도 아래처럼 처리된다.</p>
<p><img src="https://images.velog.io/images/django_apps/post/bc124223-eaef-46ff-bb88-8766cd17074e/Screen%20Shot%202021-11-02%20at%2010.50.27.png" alt=""></p>
<p>다음 포스팅에서는 원하는 유저만 접근할 수 있게 끔 <code>permission</code> 처리에 대해서 알아보도록 하자.</p>
<p>Thank you.</p>
]]></description>
        </item>
        <item>
            <title><![CDATA[[보충] Django에 대하여]]></title>
            <link>https://velog.io/@django_apps/Series03-1</link>
            <guid>https://velog.io/@django_apps/Series03-1</guid>
            <pubDate>Thu, 07 Oct 2021 05:54:06 GMT</pubDate>
            <description><![CDATA[<blockquote>
<h3 id="django란">Django란?</h3>
</blockquote>
<p>이번 포스팅에서는 <code>Django</code>　가 무엇인지에 대해서 간략히 소개해본다.</p>
<p><code>Django</code> 는 2005년부터 서비스 되고 있는 <code>python</code> 언어기반 오픈 소스 웹 프레임워크다.</p>
<p>주로 <code>backend</code> 프레임워크로 알려져있지만 <code>frontend</code> 부분도 통합하여 <code>Fullstack</code> 프레임워크로도 개발할 수 있다.</p>
<p><code>python</code> 언어로 웹 서비스를 개발한다고 한다면, <code>Django</code> or <code>Flask</code> 라고 보면 된다.</p>
<p><code>Flask</code> 는 <code>Django</code> 에 비해 경량화 된 웹 프레임워크라고 보면 된다.</p>
<blockquote>
<h3 id="django의-특징">Django의 특징</h3>
</blockquote>
<h4 id="1-orm-제공">1. ORM 제공</h4>
<p><code>Django</code> 는 MVT (Model - View - Template) 패턴을 채용하고 있다. </p>
<p><code>Model</code>의 경우 데이터베이스와 연동이 편하게 되어 있으며, 각 테이블을 <code>객체</code> 화 하여 <code>Django</code> 의 서버 로직 (<code>View</code>) 레벨에서 <code>OOP</code> 개념으로 프로그래밍 할 수 있다. 이를 <code>ORM</code> (Object-relational mapping) 이라 한다.</p>
<p>즉, 일일히 <code>DB</code> 레벨에서 <code>CRUD</code> 처리를 위해 <code>query</code> 를 작성할 필요가 없다. <code>ORM</code> 에 의해 객체의 멤버 메소드로 정의되어 있다. (e.g. create(), delete() ..)</p>
<h4 id="2-관리자-페이지-제공">2. 관리자 페이지 제공</h4>
<p><code>Django</code> 는 기본적으로 모든 <code>Model</code> 데이터를 관리할 수 있는 <code>관리자</code> 전용 폐이지를 제공한다.</p>
<p><code>Django</code> 프로젝트 내에서 관리하는 모든 테이블과 각각의 <code>CRUD</code> 처리를 관리자 페이지에서 웹 UI 기반으로 실행할 수 있다.</p>
<p>물론, <code>관리자</code>가 존재해야 하므로, <code>superuser</code>는 생성해야 한다.</p>
<p><img src="https://images.velog.io/images/django_apps/post/72a667b9-dc3e-4e60-a1ef-0770c7d27950/Screen%20Shot%202021-10-07%20at%2014.42.22.png" alt=""></p>
<h4 id="3-자주-사용되는-로직을-제공">3. 자주 사용되는 로직을 제공</h4>
<p><code>Django</code> 는 웹 프레임워크를 개발함에 있어서 누구라도 개발하기 고민되는 부분을 이미 기본적으로 제공해주고 있다. <code>CRUD API</code>는 물론, 기본 회원 인증, 데이터 직렬화, 데이터 검증, 화면에 뿌려주는 <code>Template</code> 도 기본으로 제공해 준다.</p>
<p><img src="https://images.velog.io/images/django_apps/post/10db966a-cf28-4090-b21f-02063a5fa7f6/Screen%20Shot%202021-10-07%20at%2014.41.15.png" alt=""></p>
<h4 id="4-방대한-라이브러리">4. 방대한 라이브러리</h4>
<p><code>Django</code> 는 <code>python</code> 언어 기반이기 때문에, 커뮤니티와 생태계 자체가 방대하다. 즉, <code>Django</code> 에 없는 기능이 필요할 지라도, 조금만 조사해보면 커스텀된 <code>Django</code> 전용 라이브러리가 많이 공개되어 있다.</p>
<p><img src="https://images.velog.io/images/django_apps/post/a0b08571-f8a4-4f87-8afa-b4b47560f7b1/Screen%20Shot%202021-10-07%20at%2014.39.50.png" alt=""></p>
<p>Thank you!</p>
]]></description>
        </item>
        <item>
            <title><![CDATA[[Series1. DashBoard 만들기] - 15.  회원가입 해보기]]></title>
            <link>https://velog.io/@django_apps/Series1-15</link>
            <guid>https://velog.io/@django_apps/Series1-15</guid>
            <pubDate>Mon, 27 Sep 2021 02:59:55 GMT</pubDate>
            <description><![CDATA[<blockquote>
<h3 id="회원가입-기능-api-만들기">회원가입 기능 API 만들기</h3>
</blockquote>
<p>이번 포스팅에서는 로그인 기능을 만들기 위한 전 단계인 회원가입을 API로 만들어보도록 한다.</p>
<p>처음으로 봐야할 부분은 <code>Model</code> 이다.</p>
<p><code>velog_series_01/dashboard/dashboard_core/models.py</code> 파일을 열어보자.</p>
<pre><code class="language-python"># 유저 Model을 정의한다
class PostUser(AbstractUser):
  pass</code></pre>
<p>기본적으로 유저정보에 대해 <code>django</code> 에서 템플릿을 제공해주고 있고, 우리는 그것을 가져다가 쓰기만 하기 때문에 위의 몇줄로 유저관련 <code>Model</code> 정의는 끝이다.</p>
<p>그러면, 어떤 데이터가 저장되어 있을까?</p>
<p>위 소스 코드에서 우리는 <code>PostUser</code>  Model을 정의하기 위해서 <code>AbstractUser</code> 클래스를 상속하고 있다.</p>
<p><code>AbstractUser</code> 를 살펴보면 또 <code>AbstractBaseUser</code> Model을 상속하고 있음을 알 수 있다.</p>
<p>즉, </p>
<hr>
<p><code>class AbstractBaseUser</code></p>
<p><em>password</em>
<em>last_login</em>
<em>is_active</em></p>
<p>↑</p>
<p><code>class AbstractUser</code></p>
<p><em>username</em>
<em>first_name</em>
<em>last_name</em>
<em>email</em>
<em>is_staff</em>
<em>is_active</em>
<em>date_joined</em></p>
<p>↑</p>
<p><code>class PostUser</code></p>
<hr>
<p>구조가 된다.</p>
<p>이제 <code>View</code> 부분으로 가보자.</p>
<p><code>velog_series_01/dashboard/dashboard_core/views.py</code> 파일을 열고 아래 소스를 확인한다.</p>
<pre><code class="language-python">class PostUserViewSet(ModelViewSet):
  queryset = PostUser.objects.all()

  def get_serializer_class(self):
    if self.action == &#39;list&#39;:
      return PostUserSerializer
    elif self.action == &#39;create&#39;:
      return PostUserPostSerializer
    elif self.action == &#39;update&#39;:
      return PostUserPostSerializer
    elif self.action == &#39;delete&#39;:
      return PostUserPostSerializer
    else:
      return PostUserSerializer</code></pre>
<p>저번 포스팅에서도 언급하였지만 <code>PostUserViewSet</code> 클래스가 <code>ModelViewSet</code> View를 상속하고 있으므로 <code>CRUD</code> 처리가 기본적으로 포함하고 있다.</p>
<p><code>View</code> 에서 추가적으로 해야할 작업은 없다.</p>
<p>다음은, <code>Serailzer</code> 를 확인해보자.</p>
<p><code>velog_series_01/dashboard/dashboard_core/serializers.py</code> </p>
<pre><code class="language-python">class PostUserPostSerializer(serializers.ModelSerializer):

  class Meta:
    model = PostUser
    fields = (&quot;username&quot;,&quot;password&quot;,)

  def validate_password(self, value):
    if len(value) &lt; 7:
      raise serializers.ValidationError(&quot;The password has to be at least 7 characters long!&quot;)
    return value</code></pre>
<p>간편하게 <code>username</code> 과 <code>password</code> 만 입력받게 하였으며, 덤으로 저번 포스팅에서 테스트로 작성하였던<code>password</code>는 7글자 이상으로 하지 않으면 검증에러가 나게끔 검증로직도 추가되어있다.</p>
<p>자, 마지막으로 <code>urls.py</code> 만 확인하고 테스트 해보자.</p>
<p>이미 <code>DefaultRouter</code> 를 사용하고 있기 때문에
<code>POST</code>로만 바꿔서 서버로 데이터를 송신하면 된다.</p>
<pre><code class="language-python">from dashboard_core.forms import PostUserForm

from rest_framework.routers import DefaultRouter
from dashboard_core.views import PostViewSet, PostUserViewSet

router = DefaultRouter()
router.register(r&quot;posts&quot;, PostViewSet, basename=&quot;post_status&quot;)
router.register(r&quot;users&quot;, PostUserViewSet, basename=&quot;user_status&quot;)</code></pre>
<p>이제 서버를 올리고 다음과 같이 <code>Request</code> 를 해보자.</p>
<p><code>python manage.py runserver</code></p>
<p><img src="https://images.velog.io/images/django_apps/post/d9956972-875e-4d21-9e8a-442251671fd5/Screen%20Shot%202021-09-27%20at%2012.01.25.png" alt=""></p>
<p><img src="https://images.velog.io/images/django_apps/post/acafe81e-a0e5-450e-91dd-80eb007a0251/Screen%20Shot%202021-09-27%20at%2012.02.07.png" alt=""></p>
<p><code>password</code> 를 7글자 이상으로 하고, 문제없이 처리되었다면 아래처럼 등록된 데이터가 클라이언트로 돌아온다.</p>
<p><img src="https://images.velog.io/images/django_apps/post/c69e8356-c743-4550-bbca-9bed37fd795e/Screen%20Shot%202021-09-27%20at%2012.02.52.png" alt=""></p>
<p>우리 시스템에 잘 유저가 등록되어있는지 <code>admin</code> 페이지에서 확인해보자.</p>
<p><code>http://localhost:8000/admin/</code></p>
<p><img src="https://images.velog.io/images/django_apps/post/f14854fc-89d0-4c58-b6c7-016f7f32dec7/Screen%20Shot%202021-09-27%20at%2012.04.07.png" alt=""></p>
<p><code>DATABASE_CORE</code> &gt; <code>Users</code> 에 들어가 보면
방금 등록한 유저 데이터가 조회됨을 알 수 있다!</p>
<p><img src="https://images.velog.io/images/django_apps/post/fedf5734-992f-412d-a2e3-921ffae85c27/Screen%20Shot%202021-09-27%20at%2012.04.22.png" alt=""></p>
<p>다음 포스팅에서는 <code>Login</code> 기능을 구현해보도록 한다.</p>
<p>Thank you!</p>
]]></description>
        </item>
        <item>
            <title><![CDATA[[Series1. DashBoard 만들기] - 14. Request Data 검증하기]]></title>
            <link>https://velog.io/@django_apps/Series1-14</link>
            <guid>https://velog.io/@django_apps/Series1-14</guid>
            <pubDate>Sun, 26 Sep 2021 06:07:11 GMT</pubDate>
            <description><![CDATA[<blockquote>
<h3 id="request-data-검증이-필요한-배경">Request Data 검증이 필요한 배경</h3>
</blockquote>
<p>이번 포스팅에서는 클라이언트로부터 <code>Request</code> 받은 데이터를 Model과 연계하기 전에 검증하는 방법에 대하여 알아보려 한다.</p>
<p>당연한 얘기지만, 클라이언트 단에서 어느정도 폼 데이터 검증을 거쳐서 서버로 전달되긴 하겠지만 100% 클라이언트에서 서버에서 원하는 형식으로 데이터가 온다고 보장할 수는 없다.</p>
<p>만에 하나, 서버에서 정의한 <code>Model</code> 형식대로 데이터가 오지 않을 경우에 원치 않은 에러가 나서 클라이언트로 에러 메시지가 올 가능성도 있고 오히려 에러가 나야 하는데 서버는 정상적인 데이터로 간주하여 Model 에 저장해버리는 상황도 있을 수 있다.</p>
<p><code>django</code> 에서 <code>Request</code> 받은 데이터를 체크해주는 역할은 언제까지나 Model의 스키마 정의에 위반되었는지 아닌지 정도이다.</p>
<p>그 이상으로 체크해주지 않기 때문에 직접 개발자가 <code>Request Data</code> 검증로직을 추가해줘야 한다.</p>
<p>그럼 어떻게 추가해주면 될까?</p>
<blockquote>
<h3 id="serializer에-검증-로직-추가하기">Serializer에 검증 로직 추가하기</h3>
</blockquote>
<p>바로 <code>Serializer</code> 에 원하는 검증로직을 추가하면 된다.</p>
<p>여러가지 방법이 있지만, <code>validate</code> 메소드를 Overriding 해서 해결해보자.</p>
<p>지금까지는 <code>PostUser</code> Model에 대해서 <code>API TEST</code> 를 진행했지만</p>
<p>이번부터는 DashBoard의 게시글 데이터 모델인 <code>Post</code> 를 중심으로 테스트 해보자.</p>
<p><code>velog_series_01/dashboard/dashboard_core/serializers.py</code> 파일을 열어보면 현재 최신 코드는 다음과 같을 것이다.</p>
<pre><code class="language-python">from rest_framework import serializers
from dashboard_core.models import Post, PostUser

class PostSerializer(serializers.ModelSerializer):
  title = serializers.CharField()
  contents = serializers.CharField()
  created_at = serializers.DateTimeField(read_only=True)

  class Meta:
    model = Post
    fields = &quot;__all__&quot;</code></pre>
<p>여기에 <code>validate</code> 메소드를 Overriding 하자.
검증 시나리오는 <code>Post</code> Model의 <code>title</code> 데이터가 7글자 아래라면 에러가 나도록 해보자.</p>
<p>위의 코드에 바로 아래 줄에 다음과 같이 코드를 추가하자.</p>
<pre><code class="language-python">def validate(self, attrs):
    title_val = attrs[&#39;title&#39;]
    if len(title_val) &lt; 7:
      raise serializers.ValidationError(&quot;Title has to be at least 7 characters long!&quot;)
    return attrs</code></pre>
<blockquote>
<h3 id="request-데이터-검증-테스트하기">Request 데이터 검증 테스트하기</h3>
</blockquote>
<p>이제 서버를 올리고, <code>POST</code> API로 새로운 포스트를 등록해보자.</p>
<p>1) 정상 데이터의 경우
<code>Advanced REST client</code> 툴을 넣고 아래처럼 <code>Request</code> 한다.</p>
<p><img src="https://images.velog.io/images/django_apps/post/62e8c295-d202-4510-894c-da7c9ae2984b/Screen%20Shot%202021-09-26%20at%2014.56.22.png" alt=""></p>
<p>문제가 없다면, 아래처럼 정상적으로 등록되었다고 <code>Response</code> 가 올 것이다.</p>
<p><img src="https://images.velog.io/images/django_apps/post/f127b0fb-39d7-4b33-9f82-6c37cc960942/Screen%20Shot%202021-09-26%20at%2015.01.38.png" alt=""></p>
<p>2) 정상 데이터가 아닌 경우
<code>Advanced REST client</code> 툴을 넣고 아래처럼 <code>Request</code> 한다.</p>
<p>Title이 7글자 보다 작은 데이터를 일부러 넘겨보자.</p>
<p><img src="https://images.velog.io/images/django_apps/post/6d4d1b6f-1a34-4f61-a9d2-9165fb327c96/Screen%20Shot%202021-09-26%20at%2015.03.36.png" alt=""></p>
<p><code>SEND</code> 버튼을 누르면, 아래처럼 글자수가 부족하다고 메시지가 뜨면서 등록이 실패하게 된다.</p>
<p><img src="https://images.velog.io/images/django_apps/post/0e250c91-2155-475d-b171-54eb110e3494/Screen%20Shot%202021-09-26%20at%2015.03.21.png" alt=""></p>
<p>이것으로 클라이언트에서 받은 데이터를 간단히 검증하는 법에 대해서 테스트 해보았다.</p>
<p>다음 포스팅에는 <code>API</code> 를 사용해서 로그인 / 로그아웃을 테스트 해보자.</p>
<p>Thank you!</p>
]]></description>
        </item>
        <item>
            <title><![CDATA[[Series1. DashBoard 만들기] - 13. API View 테스트 (4)]]></title>
            <link>https://velog.io/@django_apps/Series1-13</link>
            <guid>https://velog.io/@django_apps/Series1-13</guid>
            <pubDate>Sat, 25 Sep 2021 14:57:42 GMT</pubDate>
            <description><![CDATA[<blockquote>
<h3 id="유저정보-삭제-delete-api-테스트-하기">유저정보 삭제 (DELETE) API 테스트 하기</h3>
</blockquote>
<p>본 포스팅에서는 <code>PostUser</code> Model의 데이터를 삭제하기 위해 <code>DELETE API</code> 를 테스트 해보기로 한다.</p>
<p>저번 포스팅에서도 작업하였듯이 <code>API</code> 를 작성하기 위해서 아래코드가 필요하다.</p>
<ol>
<li>Router 작성 (URL 라우팅)</li>
</ol>
<pre><code class="language-python">from dashboard_core.forms import PostUserForm

from rest_framework.routers import DefaultRouter
from dashboard_core.views import PostViewSet, PostUserViewSet

router = DefaultRouter()
router.register(r&quot;posts&quot;, PostViewSet, basename=&quot;post_status&quot;)
router.register(r&quot;users&quot;, PostUserViewSet, basename=&quot;user_status&quot;)</code></pre>
<ol start="2">
<li>View 작성 (로직)</li>
</ol>
<pre><code class="language-python">from rest_framework import response
from rest_framework.viewsets import ModelViewSet
from rest_framework.permissions import IsAuthenticatedOrReadOnly
from dashboard_core.models import Post, PostUser
from dashboard_core.serializers import PostSerializer, PostUserSerializer, PostUserGetSerializer, PostUserPostSerializer

# Create your views here.
class PostViewSet(ModelViewSet):
  queryset = Post.objects.all()
  serializer_class = PostSerializer
  permission_classes = [IsAuthenticatedOrReadOnly]

class PostUserViewSet(ModelViewSet):
  queryset = PostUser.objects.all()

  def get_serializer_class(self):
    if self.action == &#39;list&#39;:
      return PostUserSerializer
    elif self.action == &#39;create&#39;:
      return PostUserPostSerializer
    elif self.action == &#39;update&#39;:
      return PostUserPostSerializer
    elif self.action == &#39;delete&#39;:
      return PostUserPostSerializer
    else:
      return PostUserSerializer</code></pre>
<ol start="3">
<li>Serializers 작성 (클라이언트에게 보내기 위해 데이터 처리)</li>
</ol>
<pre><code class="language-python">from django.db.models import fields
from rest_framework import serializers

from dashboard_core.models import Post, PostUser

class PostSerializer(serializers.ModelSerializer):
  title = serializers.CharField()
  contents = serializers.StringRelatedField()
  created_at = serializers.DateTimeField()

  class Meta:
    model = Post
    fields = &quot;__all__&quot;

class PostUserSerializer(serializers.ModelSerializer):
  username = serializers.CharField()

  class Meta:
    model = PostUser
    fields = &quot;__all__&quot;

class PostUserGetSerializer(serializers.ModelSerializer):
  username = serializers.CharField()

  class Meta:
    model = PostUser
    fields = (&quot;id&quot;, &quot;username&quot;, &quot;password&quot;,)

class PostUserPostSerializer(serializers.ModelSerializer):

  class Meta:
    model = PostUser
    fields = (&quot;username&quot;,&quot;password&quot;,)

  def validate_password(self, value):
    if len(value) &lt; 7:
      raise serializers.ValidationError(&quot;The password has to be at least 7 characters long!&quot;)
    return value</code></pre>
<p>위처럼 기본적인 위의 코드는 이미 들어가 있으므로</p>
<p>우리는 테스트만 해보면 될 것이다.</p>
<p>서버를 다음 커맨드와 같이 올린다.</p>
<p><code>python manage.py runserver</code></p>
<p>그리고 <code>Advanced REST client</code> 를 열고 아래와 같이 작성한다.</p>
<p><img src="https://images.velog.io/images/django_apps/post/93d2cb48-4124-474b-b62d-351385f36435/Screen%20Shot%202021-09-25%20at%2023.50.01.png" alt=""></p>
<p>보내고 나면 현재 데이터를 알 수 있다.</p>
<p><img src="https://images.velog.io/images/django_apps/post/4db2d5b5-1982-41c8-a3b7-293225498c9a/Screen%20Shot%202021-09-25%20at%2023.51.25.png" alt=""></p>
<p>나온 데이터들 중, <code>id</code> 가 4인 데이터가 존재한다.</p>
<p>이제부터 위 아이디에 해당하는 데이터를 지워보겠다.</p>
<p><img src="https://images.velog.io/images/django_apps/post/db4efffa-af51-480d-9737-aa0d68ec3345/Screen%20Shot%202021-09-25%20at%2023.52.44.png" alt=""></p>
<p>위처럼 <code>DELETE</code> Request를 작성하고 전송하면 아래처럼 메시지가 돌아온다.</p>
<p><img src="https://images.velog.io/images/django_apps/post/eb64a5c2-ee58-454c-adaa-af42cc1884e5/Screen%20Shot%202021-09-25%20at%2023.55.31.png" alt=""></p>
<p>자, 실제 데이터를 다시 한번 확인해보자.</p>
<p><img src="https://images.velog.io/images/django_apps/post/36763980-e645-48ab-83f3-08f91117ef4a/Screen%20Shot%202021-09-25%20at%2023.56.05.png" alt=""></p>
<p>4번째 아이디를 가진 데이터가 삭제되었음을 알 수 있다.</p>
<p>Thank you!</p>
]]></description>
        </item>
        <item>
            <title><![CDATA[[Series1. DashBoard 만들기] - 12. API View 테스트 (3)]]></title>
            <link>https://velog.io/@django_apps/Series1-12</link>
            <guid>https://velog.io/@django_apps/Series1-12</guid>
            <pubDate>Fri, 24 Sep 2021 03:14:32 GMT</pubDate>
            <description><![CDATA[<blockquote>
<h3 id="유저정보-변경-put-patch-api-테스트-하기">유저정보 변경 (PUT, PATCH) API 테스트 하기</h3>
</blockquote>
<p>지금까지 <code>PostUser</code> Model에 대하여 데이터를 가져오는 <code>GET</code> API와, 새로운 데이터를 등록하는 <code>POST</code> API에 대해서 테스트 하였다.</p>
<p>본 포스팅에서는 기존 데이터를 편집하는 <code>PUT</code>, <code>PATCH</code>  API에 대하여 테스트를 해보겠다.</p>
<p>저번 포스팅에서도 언급하였지만, 우리가 현재 API 개발에 기초로 두고 있는 클래스는 <code>ModelViewSet</code> 이다.</p>
<p>이 클래스 안에서 기본적인 API에 대해서 내부적으로 이미 개발이 되어 있기 때문에 세세한 사양변화의 Customizing 작업이나, 특별한 처리를 추가하고 싶을때를 제외하면 추가 개발은 딱히 필요 없다.</p>
<p>우리가 신경써야 할 부분은 <code>API 에서 처리할 대상을 어떻게 추릴 것이며, 클라이언트에게 돌려줄 데이터를 어떻게 정의할 것인가</code> 에 해당하는 <code>Serializer</code> 를 용도에 맞게 끔 수정해야 한다는 점이다.</p>
<p>일단 간단하게, 신규 등록은 <code>ID</code>, <code>Password</code> 정보로만 테스트 해보자.</p>
<p>프로젝트 폴더 아래에 <code>dashboard_core/views.py</code> 파일을 열고 아래와 같이 편집한다.</p>
<pre><code class="language-python">class PostUserViewSet(ModelViewSet):
  queryset = PostUser.objects.all()

  def get_serializer_class(self):
    if self.action == &#39;list&#39;:
      return PostUserSerializer
    elif self.action == &#39;create&#39;:
      return PostUserPostSerializer
    elif self.action == &#39;update&#39;:
      return PostUserPostSerializer
    elif self.action == &#39;delete&#39;:
      return PostUserPostSerializer
    else:
      return PostUserSerializer</code></pre>
<p>이것으로 각 <code>API</code>에 따라서 다른 <code>Serializer</code>를 정의하였다.</p>
<p>이제부터 딱히 소스를 만질 필요는 없지만, 간단히 유저가 요청할때부터 응답을 받을 때까지의 흐름에 대해서 다시 정리해보자.</p>
<ol>
<li><p>유저가 원하는 API로 데이터와 함께 서버에게 리퀘스트 요청을 한다.</p>
</li>
<li><p><code>django</code> 의 <code>urls.py</code> 파일(<code>DefaultRouter</code>) 에서 유저 요청을 분석하여 처리를 어느 <code>View</code> 클래스로 분기시킬지 결정한다.</p>
</li>
<li><p>해당 <code>View</code> 클래스에서 <code>action</code>에 맞게 데이터 처리를 시행한다.</p>
</li>
</ol>
<p><code>action</code> 이란, <code>ModelViewSet</code> 클래스 기준으로 <code>create</code>, <code>retrieve</code>,
<code>update</code>, <code>partial_update</code>,
<code>destroy</code>, <code>list</code> 의 총 6가지로 나뉜다.</p>
<ol start="4">
<li>처리가 끝난 데이터는 <code>Serializer</code> 에 의해, <code>JSON</code> 형태로 클라이언트에 돌려진다.</li>
</ol>
<p>이상, 처리 Cycle은 끝이다.</p>
<p><code>django</code>와 <code>restframework</code> 에서 내부적으로 처리해주는 부분이 많기 때문에 이해가 힘들수도 있겠지만 그럴수록 더 흐름에 대해서 만큼은 빠삭하게 알고 있어야 한다.</p>
<p>자, 본격적으로 기존 데이터를 <code>PUT</code> API를 이용하여 수정해보자.</p>
<p>서버를 실행하자.</p>
<p><code>python manage.py runserver</code></p>
<p>이어서 <code>Advanced REST Client</code> 를 열고, 아래와 같이 <code>GET</code> API를 리퀘스트 한다.</p>
<p><img src="https://images.velog.io/images/django_apps/post/615b963d-9040-419c-8c1c-1c6779eaea2c/Screen%20Shot%202021-09-24%20at%2011.58.40.png" alt=""></p>
<p>결과는 아래와 같다.</p>
<p><img src="https://images.velog.io/images/django_apps/post/d80e2685-4bf4-44fa-a737-4af9044754c4/Screen%20Shot%202021-09-24%20at%2011.59.27.png" alt=""></p>
<p>위와 같이 현재 데이터가 확인되었으니
<code>id</code>가 3인 데이터(<code>username</code>: <code>test1</code>, <code>password</code>: <code>123123123</code>)를 아래와 같이 수정해보도록 하자. </p>
<pre><code class="language-json">{
  &quot;username&quot;: &quot;test3&quot;,
  &quot;password&quot;: &quot;4564567&quot;
}</code></pre>
<p>아래와 같이 <code>PUT</code> API 리퀘스트 양식을 작성한다.</p>
<p><img src="https://images.velog.io/images/django_apps/post/ffc17105-2d87-448e-b6bb-acd7bef2ccee/Screen%20Shot%202021-09-24%20at%2012.05.14.png" alt=""></p>
<p>전송해서 성공하면, 아래처럼 서버로부터 갱신된 데이터를 클라이언트로 반환시켜준다.</p>
<p><img src="https://images.velog.io/images/django_apps/post/c6fcd583-2159-40ed-a760-e04f6a17a4c0/Screen%20Shot%202021-09-24%20at%2012.05.43.png" alt=""></p>
<p>리퀘스트 요청대로 잘 처리되었음을 알 수 있다.</p>
<p>이어서, 부분적인 데이터만 수정하는 <code>PATCH</code> API를 테스트해보자.</p>
<p>방금전에 수정했던 데이터의 <code>username</code> 필드만 수정해보겠다.</p>
<p>아래와 같이 리퀘스트를 작성한다.</p>
<p><img src="https://images.velog.io/images/django_apps/post/9e406db1-7d54-4da5-bdac-8888beb0755a/Screen%20Shot%202021-09-24%20at%2012.08.54.png" alt=""></p>
<p><code>SEND</code> 버튼을 눌러서 서버에 리퀘스트하면, 변경사항이 반영된 전체 <code>PostUser</code> Model의 데이터가 반환됨을 알 수 있다.</p>
<p><img src="https://images.velog.io/images/django_apps/post/9c6b3826-5c08-4330-bcfc-43531f247386/Screen%20Shot%202021-09-24%20at%2012.09.22.png" alt=""></p>
<p>지금까지 수정 API인 <code>PUT</code>과 <code>PATCH</code>를 각각 테스트 해보았다.</p>
<p>여기서 <code>POST</code> API 와의 차이점에 대해서 간단히 정리해보겠다. </p>
<p><code>Serailizer</code> 에 정의된 모든 필드를 다 서버에 넘겨줘야만 하는 <code>POST</code> API라면, 정의된 필드중에서 수정하고싶은 몇개 필드만 넘기고 싶을 때에는 <code>PATCH</code> API를 사용한다고 보면 이해가 쉽다.</p>
<p>다음 포스팅에는 삭제하는 <code>DELETE</code> API에 대하여 테스트 해보도록 한다.</p>
<p>Thank you!</p>
]]></description>
        </item>
        <item>
            <title><![CDATA[[Series1. DashBoard 만들기] - 11. API View 테스트 (2)]]></title>
            <link>https://velog.io/@django_apps/Series1-11</link>
            <guid>https://velog.io/@django_apps/Series1-11</guid>
            <pubDate>Wed, 22 Sep 2021 22:58:51 GMT</pubDate>
            <description><![CDATA[<blockquote>
<h3 id="유저등록-post-api-테스트-하기">유저등록 POST API 테스트 하기</h3>
</blockquote>
<p>유저에 대한 CRUD API를 계속해서 작성해보도록 하자.</p>
<p>이번에는 유저등록 부분이다. <code>POST API</code> 테스트를 해보도록 하자!</p>
<p>저번 포스팅에서 이미 모든 <code>CRUD API</code> 가 포함된 <code>ModelViewSet</code> 클래스를 상속하여 View를 생성했었기 때문에 <code>POST API</code> 테스트를 위해서 추가 작업은 필요하지 않다.</p>
<p>하지만, 현재 <code>PostUserViewSet</code> View 클래스는 <code>PostUser</code> Model의 모든 데이터를 반환하기 때문에 효율적이지 않다. 필요한 데이터만 클라이언트에게 받아서 회원등록 <code>POST API</code> 을 테스트 해보자.</p>
<p>일단 <code>PostUser</code> Model의 <code>Serializer</code> 를 <code>POST API</code> 용으로 하나 더 만들자.</p>
<p><code>velog_series_01/dashboard/dashboard_core/serializer.py</code> 파일을 열고, 아래와 같이 <code>PostUserPostSerializer</code> 클래스를 추가한다.</p>
<pre><code class="language-python">class PostUserPostSerializer(serializers.ModelSerializer):

  class Meta:
    model = PostUser
    fields = (&quot;username&quot;,&quot;password&quot;,)</code></pre>
<p>위 코드에서 확인할 수 있듯이 <code>PostUser</code> Model 신규데이터 등록에 필요한 필드는 <code>POST API</code> 테스트를 보다 간편하게 만들기 위해서 <code>username</code> 과 <code>password</code> 으로만 제한하였다.</p>
<p>위 코드를 추가한 후에 <code>serializer.py</code> 파일의 전체 코드는 아래와 같다.</p>
<pre><code class="language-python">from django.db.models import fields
from rest_framework import serializers

from dashboard_core.models import Post, PostUser

class PostSerializer(serializers.ModelSerializer):
  title = serializers.CharField()
  contents = serializers.StringRelatedField()
  created_at = serializers.DateTimeField()

  class Meta:
    model = Post
    fields = &quot;__all__&quot;

class PostUserSerializer(serializers.ModelSerializer):
  username = serializers.CharField()

  class Meta:
    model = PostUser
    fields = &quot;__all__&quot;

class PostUserPostSerializer(serializers.ModelSerializer):

  class Meta:
    model = PostUser
    fields = (&quot;username&quot;,&quot;password&quot;,)</code></pre>
<p>마지막으로 <code>views.py</code> 파일을 열어서 <code>PostUserViewSet</code> 클래스를 아래와 같이 수정하여 <code>PostUserPostSerializer</code> 클래스를 추가한다.</p>
<pre><code class="language-python">class PostUserViewSet(ModelViewSet):
  queryset = PostUser.objects.all()

  def get_serializer_class(self):
    if self.action == &#39;create&#39;:
      return PostUserPostSerializer
    else:
      return PostUserSerializer</code></pre>
<p>위 코드를 적용함으로써 클라이언트로부터 <code>POST</code> 요청이 오면, <code>ModelViewSet</code> 클래스에 적용하는 <code>Serializer</code> 클래스를 <code>PostUserPostSerializer</code> 로 바꿔준다.</p>
<p>이제 <code>Advanced REST client</code> 로 아래와 같이 <code>POST</code> 로 유저등록 데이터와 함께 <code>Request</code> 를 보낸다.</p>
<p><img src="https://images.velog.io/images/django_apps/post/6a3cb9f4-0dc2-41b5-9d11-d140919a9c8c/Screen%20Shot%202021-09-23%20at%207.46.18.png" alt=""></p>
<p>아래처럼 서버로부터 <code>201 OK</code> 메시지가 도착하였다.
정상처리가 되었음을 의미한다!</p>
<p><img src="https://images.velog.io/images/django_apps/post/fb9ed037-7f8d-44af-9cd9-6941a6221f9e/Screen%20Shot%202021-09-23%20at%207.53.18.png" alt=""></p>
<p>이제 직접 웹브라우저에서 방금 추가한 유저정보가 로드되는지 확인해보자.</p>
<p><code>http://127.0.0.1:8000/users/</code></p>
<p>아래에서 우리가 방금 추가했던 유저정보가 등록되어있음을 알 수 있다!</p>
<p><img src="https://images.velog.io/images/django_apps/post/c65e48f3-4d0d-43c3-befe-c66fa003d7e0/Screen%20Shot%202021-09-23%20at%207.56.02.png" alt=""></p>
<p>이번 포스팅에서는 <code>PostUser</code> Model의 <code>POST API</code> 테스트를 해보았다.</p>
<p>다음에는 이어서 <code>UPDATE API</code> 테스트에 대해서 알아보겠다.</p>
<p>Thank you!</p>
]]></description>
        </item>
        <item>
            <title><![CDATA[[Series1. DashBoard 만들기] - 10. API View 테스트 (1)]]></title>
            <link>https://velog.io/@django_apps/Series1-10</link>
            <guid>https://velog.io/@django_apps/Series1-10</guid>
            <pubDate>Wed, 22 Sep 2021 14:01:06 GMT</pubDate>
            <description><![CDATA[<blockquote>
<h3 id="유저등록-get-api-테스트-하기">유저등록 GET API 테스트 하기</h3>
</blockquote>
<p>이번 포스팅부터는 본격적으로 유저에 대해 <code>CRUD</code> API를 작성해보도록 하자.</p>
<p>처음은 <code>유저조회</code> 부분이다. 즉, <code>GET API</code> 테스트를 해보자.</p>
<p>일단 <code>PostUser</code> Model에 대한 <code>Serializer</code> 를 개발한다.</p>
<p><code>velog_series_01/dashboard/dashboard_core/serializers.py</code> 파일을 열어 아래와 같이 추가한다.</p>
<pre><code class="language-python">from rest_framework import serializers

from dashboard_core.models import Post, PostUser

class PostSerializer(serializers.ModelSerializer):
  title = serializers.CharField()
  contents = serializers.StringRelatedField()
  created_at = serializers.DateTimeField()

  class Meta:
    model = Post
    fields = &quot;__all__&quot;

class PostUserSerializer(serializers.ModelSerializer):
  username = serializers.CharField()

  class Meta:
    model = PostUser
    fields = &quot;__all__&quot;
</code></pre>
<p>그리고 같은 위치의 <code>views.py</code> 파일에 <code>CRUD</code> API가 포함되어 있는 <code>ModelViewSet</code> 클래스를 상속하여 아래와 같이 추가해준다.</p>
<pre><code class="language-python">from rest_framework.viewsets import ModelViewSet
from rest_framework.permissions import IsAuthenticatedOrReadOnly
from dashboard_core.models import Post, PostUser
from dashboard_core.serializers import PostSerializer, PostUserSerializer

# Create your views here.
class PostViewSet(ModelViewSet):
  queryset = Post.objects.all()
  serializer_class = PostSerializer
  permission_classes = [IsAuthenticatedOrReadOnly]

class PostUserViewSet(ModelViewSet):
  queryset = PostUser.objects.all()
  serializer_class = PostUserSerializer</code></pre>
<p>위 작업으로, <code>CRUD</code> API가 자동으로 추가된다.
이해가 되지 않는다면, <code>ModelViewSet</code> 클래스를 살펴보자.</p>
<pre><code class="language-python">class ModelViewSet(mixins.CreateModelMixin,
                   mixins.RetrieveModelMixin,
                   mixins.UpdateModelMixin,
                   mixins.DestroyModelMixin,
                   mixins.ListModelMixin,
                   GenericViewSet):
    &quot;&quot;&quot;
    A viewset that provides default `create()`, `retrieve()`, `update()`,
    `partial_update()`, `destroy()` and `list()` actions.
    &quot;&quot;&quot;
    pass</code></pre>
<p>위에서 보다시피</p>
<p>C(<code>mixins.CreateModelMixin</code>),
R(<code>mixins.RetrieveModelMixin</code>, <code>mixins.ListModelMixin</code>),
U(<code>mixins.UpdateModelMixin</code>),
D(<code>mixins.DestroyModelMixin</code>)</p>
<p>4가지의 API 처리가 이미 포함되어 있음을 알 수 있다.</p>
<p>이제 마지막은 <code>urls.py</code> 파일에 <code>PostUser</code> Model에 대한 URL을 <code>DefaultRouter</code> 을 이용해서 추가한다.</p>
<pre><code class="language-python">router = DefaultRouter()
router.register(r&quot;posts&quot;, PostViewSet, basename=&quot;post_status&quot;)
router.register(r&quot;users&quot;, PostUserViewSet, basename=&quot;user_status&quot;)</code></pre>
<p>드디어 <code>GET API</code> 를 테스트 할 준비가 되었다.</p>
<p>서버를 가동한 다음,</p>
<p><code>python manage.py runserver</code></p>
<p><code>Advanced REST Client</code> 같은 API Client Test Tool을 열어서 <code>GET</code> API로 리퀘스트를 설정한다.</p>
<p><img src="https://images.velog.io/images/django_apps/post/288e708c-a073-4fee-8ea5-4a10bf8cf8fa/Screen%20Shot%202021-09-23%20at%203.09.03.png" alt=""></p>
<p><code>SEND</code> 를 눌러서 <code>Response</code> 객체를 확인한다.
아래처럼 현재의 유저정보 로드에 성공하였다!</p>
<p><img src="https://images.velog.io/images/django_apps/post/17a7bcae-2928-4b85-945e-e782357d0dd9/Screen%20Shot%202021-09-23%20at%203.10.14.png" alt=""></p>
<p>서버 로그를 보면, <code>200 OK</code> 정상 처리가 됬음을 확인할 수 있다.</p>
<p><img src="https://images.velog.io/images/django_apps/post/5bbeb0b3-45df-4316-834d-ccda9e84d9d4/Screen%20Shot%202021-09-23%20at%203.10.45.png" alt=""></p>
<p>이것으로 <code>GET API</code> 처리가 잘 되는지 테스트 해보았다.</p>
<p>다음 포스팅에서는 이어서 <code>POST API</code> 에 대해서 테스트 해보겠다.</p>
<p>Thank you!</p>
]]></description>
        </item>
        <item>
            <title><![CDATA[[Series1. DashBoard 만들기] - 9. View 만들기 (4)]]></title>
            <link>https://velog.io/@django_apps/Series1-9</link>
            <guid>https://velog.io/@django_apps/Series1-9</guid>
            <pubDate>Tue, 21 Sep 2021 02:20:18 GMT</pubDate>
            <description><![CDATA[<blockquote>
<h3 id="유저-등록-가상-폼-작성과-view-연계">유저 등록 가상 폼 작성과 View 연계</h3>
</blockquote>
<p>  오늘 포스팅은, 직전 포스팅에 이어서 유저 등록 가상 폼을 작성하여 <code>PostUser</code> View와 연계해보도록 하겠다.</p>
<p><code>velog_series_01/dashboard/dashboard_core</code> 아래에 <code>forms.py</code> 파일을 신규 생성한다.</p>
<p>그리고 다음과 같이 작성한다.</p>
<pre><code class="language-python">from django_registration.forms import RegistrationForm
from dashboard_core.models import PostUser

class PostUserForm(RegistrationForm):

  class Meta(RegistrationForm.Meta):
    model = PostUser</code></pre>
<p>가상 폼 포맷은 작성하였으니 URL에 가상 폼을 등록하자.</p>
<p><code>velog_series_01/dashboard/dashboard</code> 에서 <code>urls.py</code> 을 열고 아래와 같이 추가해주자.</p>
<pre><code class="language-python"> .
 .
 .
from django_registration.backends.one_step.views import RegistrationView
from dashboard_core.forms import PostUserForm
 .
 .
 .</code></pre>
<pre><code class="language-python">urlpatterns = [
 .
 .
 .
    path(&#39;accounts/register/&#39;, RegistrationView.as_view(
            form_class=PostUserForm,
            success_url=&#39;/&#39;
        ), name=&#39;django_registration_register&#39;),
 .
 .
 .
]</code></pre>
<p>다음으로 <code>settings.py</code> 파일에서 로그인 / 아웃 후에 자동 다이렉트 페이지 URL을 추가해준다.</p>
<pre><code class="language-python">  .
  .
  .
USE_L10N = True

USE_TZ = True

LOGIN_URL = &quot;accounts/login/&quot;
LOGIN_REDIRECT_URL = &quot;/&quot;
LOGOUT_REDIRECT_URL = &quot;/&quot;

# Static files (CSS, JavaScript, Images)
# https://docs.djangoproject.com/en/3.2/howto/static-files/

STATIC_URL = &#39;/static/&#39;

  .
  .
  .</code></pre>
<p>다음으로, 로그인 기능 관련해서 페이지에 간단히 로그인 정보를 표시해줄 <code>template</code> 을 만들어 보자.</p>
<p><code>velog_series_01/dashboard/dashboard</code> 폴더 아래에 아래와 같이 폴더와 파일을 만든다.</p>
<ul>
<li>dashboard (<code>velog_series_01/dashboard/dashboard</code>)</li>
<li><ul>
<li>templates (폴더)</li>
</ul>
</li>
<li><ul>
<li>-- django_registration (폴더)</li>
</ul>
</li>
<li><ul>
<li>-- -- registration_form.html (파일)</li>
</ul>
</li>
<li><ul>
<li>-- registration (폴더)</li>
</ul>
</li>
<li><ul>
<li>-- -- login.html (파일)</li>
</ul>
</li>
<li><ul>
<li>-- auth_layout.html (파일)</li>
</ul>
</li>
</ul>
<p>그리고 <code>settings.py</code> 에서 <code>TEMPLATES</code> &gt; <code>DIRS</code> 에 <code>templates</code> 폴더 패스를 등록한다.</p>
<pre><code class="language-python">TEMPLATES = [
    {
        &#39;BACKEND&#39;: &#39;django.template.backends.django.DjangoTemplates&#39;,
        &#39;DIRS&#39;: [BASE_DIR / &#39;dashboard&#39; / &#39;templates&#39;],
        &#39;APP_DIRS&#39;: True,
        &#39;OPTIONS&#39;: {
            &#39;context_processors&#39;: [
                &#39;django.template.context_processors.debug&#39;,
                &#39;django.template.context_processors.request&#39;,
                &#39;django.contrib.auth.context_processors.auth&#39;,
                &#39;django.contrib.messages.context_processors.messages&#39;,
            ],
        },
    },
]</code></pre>
<p>이제 <code>templates</code> 폴더의 아래 3개 파일을 아래와 같이 작성한다.
<code>auth_layout.html</code>
<code>registration_form.html</code>
<code>login.html</code></p>
<ol>
<li><code>auth_layout.html</code></li>
</ol>
<pre><code class="language-html">&lt;html&gt;
  &lt;head&gt;
    &lt;meta charset=&quot;utf-8&quot; /&gt;
    &lt;meta http-equiv=&quot;X-UA-Compatible&quot; content=&quot;IE=edge&quot; /&gt;
    &lt;meta name=&quot;description&quot; content=&quot;&quot; /&gt;
    &lt;meta name=&quot;viewport&quot; content=&quot;width=device-width, initial-scale=1&quot; /&gt;
    &lt;title&gt;Post&lt;/title&gt;
    &lt;link rel=&quot;stylesheet&quot;
    href=&quot;https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/css/bootstrap.min.css&quot;
    integrity=&quot;sha384-BVYiiSIFeK1dGmJRAkycuHAHRg32OmUcww7on3RYdg4Va+PmSTsz/K68vbdEjh4u&quot;
    crossorigin=&quot;anonymous/&gt;
    &lt;style&gt;
      .login-form-container {
        width: 300px;
        margin: auto;
      }

      .registration-form-container {
        width: 400px;
        margin: auto;
      }
    &lt;/style&gt;
  &lt;/head&gt;
  &lt;body&gt;
    &lt;div class=&quot;auth-box text-center&quot;&gt;{% block content %} {% endblock %}&lt;/div&gt;
  &lt;/body&gt;
&lt;/html&gt;</code></pre>
<ol start="2">
<li><code>registration_form.html</code></li>
</ol>
<pre><code class="language-html">{% extends &#39;auth_layout.html&#39; %} {% load crispy_forms_tags %} {% block content%}
&lt;h1&gt;Create your account&lt;/h1&gt;
&lt;div class=&quot;registration-form-container&quot;&gt;
  &lt;form method=&quot;POST&quot;&gt;
    {% csrf_token %} {{ form|crispy }}
    &lt;button type=&quot;submit&quot; class=&quot;btn btn-sm btn-outline-primary&quot;&gt;
      Create an user
    &lt;/button&gt;
  &lt;/form&gt;
&lt;/div&gt;
{% endblock %}</code></pre>
<ol start="3">
<li><code>login.html</code></li>
</ol>
<pre><code class="language-html">{% extends &#39;auth_layout.html&#39; %} {% load crispy_forms_tags %} {% block content
%}
&lt;h1&gt;Login&lt;/h1&gt;
&lt;div class=&quot;login-form-container&quot;&gt;
  &lt;form method=&quot;POST&quot;&gt;
    {% csrf_token %} {{ form|crispy }}
    &lt;button type=&quot;submit&quot; class=&quot;btn btn-sm btn-outline-primary&quot;&gt;Login&lt;/button&gt;
  &lt;/form&gt;
&lt;/div&gt;
{% endblock %}</code></pre>
<p>위의 파일들을 저장하고, 서버를 올려서 아래 URL로 접근해보자.</p>
<p><code>python manage.py runserver</code></p>
<p><code>http://127.0.0.1:8000/accounts/register/</code></p>
<p>아래처럼 회원등록 폼이 나타나면 성공이다!</p>
<p><img src="https://images.velog.io/images/django_apps/post/8b8d5622-39c7-4e58-86cd-0bfa52003180/Screen%20Shot%202021-09-21%20at%2013.14.13.png" alt=""></p>
<p>위에 화면에서 한번 회원등록을 해보자.</p>
<p>등록하자마자, <code>http://127.0.0.1:8000/</code> 페이지로 리다이렉트 된다.</p>
<p><img src="https://images.velog.io/images/django_apps/post/bfbab85d-9bd1-4688-8d26-63adb48274c4/Screen%20Shot%202021-09-21%20at%2013.15.21.png" alt=""></p>
<p>우상단 화면에 방금전에 가입한 <code>Username</code> 이 표시됨을 알수있다.</p>
<p>자, 실제로 유저관리화면에 추가되었는지 확인해보자.</p>
<p>아래 <code>admin</code> 계정으로 관리화면에 로그인 해보자.</p>
<p><code>http://127.0.0.1:8000/admin</code></p>
<p><img src="https://images.velog.io/images/django_apps/post/3032a28d-3975-40e9-b872-1d481184349f/Screen%20Shot%202021-09-21%20at%2013.19.15.png" alt=""></p>
<p><code>Users</code> Model 을 조회해보자.
아래처럼, 방금 추가한 <code>Username</code> 이 존재함을 알 수 있다.</p>
<p><img src="https://images.velog.io/images/django_apps/post/ed1a3c2a-1851-49ff-a2bf-111d1f3b49b9/Screen%20Shot%202021-09-21%20at%2013.19.46.png" alt=""></p>
<p>이것으로 가상폼이긴 하나, 유저 모델을 추가해서 <code>django</code> 프로젝트의 <code>Post</code> 모델과 연계하여 보았다.</p>
<p>다음 포스팅에서는 실제<code>API</code>로 확장해서, 클라이언트에서 직접 <code>Request</code> 로 받아서 처리 하는 로직을 작성해보겠다.</p>
<p>Thank you!</p>
]]></description>
        </item>
        <item>
            <title><![CDATA[[Series1. DashBoard 만들기] - 8. View 만들기 (3)]]></title>
            <link>https://velog.io/@django_apps/Series1.-DashBoard-%EB%A7%8C%EB%93%A4%EA%B8%B0-8.-View-%EB%A7%8C%EB%93%A4%EA%B8%B0-3</link>
            <guid>https://velog.io/@django_apps/Series1.-DashBoard-%EB%A7%8C%EB%93%A4%EA%B8%B0-8.-View-%EB%A7%8C%EB%93%A4%EA%B8%B0-3</guid>
            <pubDate>Tue, 21 Sep 2021 00:46:15 GMT</pubDate>
            <description><![CDATA[<blockquote>
<h3 id="유저-모델-등록">유저 모델 등록</h3>
</blockquote>
<p>  이번 포스팅에서는 유저 등록하는 부분을 가상 폼을 이용해서 만들어 보자.</p>
<p>처음에 해야 할 부분은 Model에 유저정보 모델 (<code>PostUser</code>) 을 추가하는 것이다.</p>
<p><code>velog_series_01/dashboard/dashboard_core/models.py</code> 파일을 열고 다음을 추가한다.</p>
<pre><code class="language-python"># 유저 Model을 정의한다
class PostUser(AbstractUser):
  pass</code></pre>
<p>코드를 추가한 <code>models.py</code> 파일은 다음과 같다.</p>
<pre><code class="language-python">from django.db import models
from django.contrib.auth.models import AbstractUser

# Create your models here.

# DashBoard 게시글 Model을 정의한다
class Post(models.Model):
  title = models.CharField(max_length=60)
  contents = models.TextField()
  created_at = models.DateTimeField(auto_now_add=True)

# 유저 Model을 정의한다
class PostUser(AbstractUser):
  pass</code></pre>
<p>다음으로 유저를 인증하기 위한 Model을 <code>settings.py</code> 파일 마지막줄에 아래와 같이 추가한다.</p>
<pre><code class="language-python">AUTH_USER_MODEL = &#39;dashboard_core.PostUser&#39;</code></pre>
<p>이어서 <code>admin.py</code> 파일을 열고,  <code>django</code> 의 <code>admin</code> 내장 모듈에 방금전에 추가했던 유저정보 모델 <code>PostUser</code> 을 추가한다.</p>
<pre><code class="language-python">from django.contrib import admin
from django.contrib.auth.admin import UserAdmin
from dashboard_core.models import Post, PostUser

class CustomUserAdmin(UserAdmin):
  model = PostUser
  list_display = [&quot;username&quot;, &quot;email&quot;, &quot;is_staff&quot;]

# Register your models here.
admin.site.register(Post)
admin.site.register(PostUser, CustomUserAdmin)</code></pre>
<p>기본적인 작업은 이것으로 끝이다.</p>
<p>하지만, <code>PostUser</code> Model을 추가했기 때문에 다시 <code>migration</code> 을 해줘야 한다. 다음 커맨드를 실행한다.</p>
<p><code>python manage.py migrate</code></p>
<p>지금까지 <code>django</code> 에 <code>Post</code> Model과 연계하기 위한 <code>User</code> Model을 만들어보았다.</p>
<p>이제는 인증 모듈과 연계할 차례다.</p>
<p>다음 커맨드로 유저 인증처리 / 유저 등록에 필요한 패키지를 설치한다.</p>
<p><code>pip install django-rest-auth</code></p>
<p><code>pip install django-allauth</code></p>
<p><code>pip install django-registration</code></p>
<p><code>pip install django-crispy-forms</code></p>
<p>설치가 다 되었다면, <code>settings.py</code> 파일의 <code>INSTALLED_APPS</code> 배열에 추가한다.</p>
<p>추가한 최종 코드는 아래와 같다.</p>
<pre><code class="language-python">INSTALLED_APPS = [
    &#39;django.contrib.admin&#39;,
    &#39;django.contrib.auth&#39;,
    &#39;django.contrib.contenttypes&#39;,
    &#39;django.contrib.sessions&#39;,
    &#39;django.contrib.messages&#39;,
    &#39;django.contrib.staticfiles&#39;,
    &#39;django.contrib.sites&#39;,

    &#39;rest_framework&#39;,
    &#39;rest_framework.authtoken&#39;,

    &#39;allauth&#39;,
    &#39;allauth.account&#39;,
    &#39;allauth.socialaccount&#39;,

    &#39;rest_auth&#39;,
    &#39;rest_auth.registration&#39;,

    &#39;crispy_forms&#39;,

    &#39;dashboard_core&#39;,
]</code></pre>
<p>그리고 <code>settings.py</code> 파일의 맨 아랫줄에 유저등록 폼 template / 인증관련 설정을 추가해준다.</p>
<pre><code class="language-python"># django-crispy-forms
CRISPY_TEMPLATE_PACK = &quot;bootstrap4&quot;

# django-allauth
ACCOUNT_EMAIL_VERIFICATION = &quot;none&quot;
ACCOUNT_EMAIL_REQUIRED = (True)</code></pre>
<p>방금 설치한 패키지가 <code>django</code> Model에 영향을 주기 때문에, 다시 한번 <code>migrate</code> 를 실행하자.</p>
<p><code>python manage.py migrate</code></p>
<p><img src="https://images.velog.io/images/django_apps/post/cad25642-3026-4482-9185-4409902f6a1b/Screen%20Shot%202021-09-21%20at%209.03.34.png" alt=""></p>
<p><code>migrate</code> 작업이 완료되었다.</p>
<p>이제 설치된 유저인증 패키지를 Request URL과 연결시키기 위해 <code>urls.py</code> 파일에 추가해준다.</p>
<p>추가한 후에 <code>urls.py</code> 의 전체 소스는 다음과 같다.</p>
<pre><code class="language-python">from django.contrib import admin
from django.urls import include, path
from rest_framework.routers import DefaultRouter
from dashboard_core.views import PostViewSet

router = DefaultRouter()
router.register(r&quot;posts&quot;, PostViewSet, basename=&quot;post_status&quot;)

urlpatterns = [
    path(&#39;&#39;, include(router.urls)),
    path(&#39;admin/&#39;, admin.site.urls),
    path(&#39;accounts/&#39;, include(&#39;django.contrib.auth.urls&#39;)),
    path(&#39;api-auth/&#39;, include(&#39;rest_framework.urls&#39;)),
    path(&#39;rest-auth/&#39;, include(&#39;rest_auth.urls&#39;)),
    path(&#39;rest-auth/registration/&#39;, include(&#39;rest_auth.registration.urls&#39;)),
]</code></pre>
<p>이것으로 유저 인증 / 등록에 관련된 패키지의 설치 및 우리의 <code>django &gt; dashboard</code> 프로젝트, 앱에 연계관련하여 개발을 진행하였다.</p>
<p>다음 포스팅에서는 실제로 가상 유저등록 <code>Form</code> 을 만들어보도록 하겠다.</p>
<p>Thank you!</p>
]]></description>
        </item>
        <item>
            <title><![CDATA[[Series1. DashBoard 만들기] - 7. View 만들기 (2)]]></title>
            <link>https://velog.io/@django_apps/Series1-7</link>
            <guid>https://velog.io/@django_apps/Series1-7</guid>
            <pubDate>Sun, 19 Sep 2021 06:18:00 GMT</pubDate>
            <description><![CDATA[<p>이번 포스팅에서는, View의 CRUD 처리를 추가하고 <code>django/restframework</code> 의 User 등록관련 모듈을 추가하여 권한처리를 위한 최소 준비를 해보자.</p>
<blockquote>
<h3 id="user-회원등록--로그인-기능을-추가하자">User 회원등록 / 로그인 기능을 추가하자</h3>
</blockquote>
<p><code>django</code> 에서는 <code>restframework</code> 라는 API 개발 라이브러리를 추가하여 간단히 회원관련 기능을 만들 수 있다.</p>
<p>먼저 필요한 라이브러리를 <code>pip</code> 커맨드를 이용하여 설치한다.</p>
<p>아래 커맨드를 실행한다.</p>
<p><code>pip install django-allauth</code>
<code>pip install django-rest-auth</code></p>
<p>문제 없이 설치되었다면 <code>settings.py</code> 에서 아래 앱들을</p>
<pre><code>    &#39;allauth&#39;,
    &#39;allauth.account&#39;,
    &#39;allauth.socialaccount&#39;,
    &#39;rest_auth&#39;,
    &#39;rest_auth.registration&#39;,</code></pre><p><code>INSTALLED_APPS</code> 배열에 추가하자</p>
<pre><code class="language-python"># Application definition

INSTALLED_APPS = [
    &#39;django.contrib.admin&#39;,
    &#39;django.contrib.auth&#39;,
    &#39;django.contrib.contenttypes&#39;,
    &#39;django.contrib.sessions&#39;,
    &#39;django.contrib.messages&#39;,
    &#39;django.contrib.staticfiles&#39;,
    &#39;django.contrib.sites&#39;,

    &#39;rest_framework&#39;,

    &#39;allauth&#39;,
    &#39;allauth.account&#39;,
    &#39;allauth.socialaccount&#39;,
    &#39;rest_auth&#39;,
    &#39;rest_auth.registration&#39;,

    &#39;dashboard_core&#39;,
]</code></pre>
<p>다음으로는, User가 접근할 회원가입 관련 URL을 매핑해준다.</p>
<p><code>velog_series_01/dashboard/dashboard/urls.py</code> 파일을 열고 아래와 같이 편집한다.</p>
<pre><code class="language-python">from django.contrib import admin
from django.urls import include, path
from rest_framework.routers import DefaultRouter
from dashboard_core.views import PostViewSet

router = DefaultRouter()
router.register(r&quot;posts&quot;, PostViewSet, basename=&quot;post_status&quot;)

urlpatterns = [
    path(&#39;&#39;, include(router.urls)),
    path(&#39;admin/&#39;, admin.site.urls),
    path(&#39;api-auth/&#39;, include(&#39;rest_framework.urls&#39;)),
    path(&#39;rest-auth&#39;, include(&#39;rest_auth.urls&#39;)),
    path(&#39;rest-auth/registration&#39;, include(&#39;rest_auth.registration.urls&#39;)),
]</code></pre>
<p>이제 회원가입에 관련된 앱들도 설치했고 자동으로 해당하는 모델이 추가되었기 때문에, DB와 sync를 맞추기 위해 <code>Migrate</code> 가 필요하다.</p>
<p>아래 커맨드를 실행하자.</p>
<p><code>python manage.py migrate</code></p>
<p><img src="https://images.velog.io/images/django_apps/post/33b6eb38-8044-4fbf-a476-0b1ffb53a633/Screen%20Shot%202021-09-19%20at%2014.39.24.png" alt=""></p>
<p>무사히 성공한다!</p>
<p>마지막으로 <code>settings.py</code> 파일 맨 아래에 회원 인증 방식에 대한 설정과, site 번호를 넣어준다.</p>
<pre><code class="language-python">REST_FRAMEWORK = {
    &#39;DEFAULT_AUTHENTICATION_CLASSES&#39;: [
        &#39;rest_framework.authentication.SessionAuthentication&#39;,
        &#39;rest_framework.authentication.TokenAuthentication&#39;,
    ]
}

SITE_ID = 1</code></pre>
<p>이제 서버를 실행하고, <code>http://127.0.0.1:8000/</code> 에 접속해보자.</p>
<p><img src="https://images.velog.io/images/django_apps/post/c45ad9e2-2133-48e8-90cd-e0980e8a9c56/Screen%20Shot%202021-09-19%20at%2015.11.09.png" alt=""></p>
<p>오른쪽 상단에 <code>Login</code> 버튼에 생겼다.
버튼을 눌러, 관리자 계정으로 로그인 해보자.</p>
<p><img src="https://images.velog.io/images/django_apps/post/65d05d2d-d2fa-4fe4-ad6c-8da2bca32a4e/Screen%20Shot%202021-09-19%20at%2015.13.03.png" alt=""></p>
<p>로그인 한뒤에, <code>Post</code> URL로 이동해보자.</p>
<p><img src="https://images.velog.io/images/django_apps/post/d2220c6b-dd84-46f1-8411-8ae3648b0750/Screen%20Shot%202021-09-19%20at%2015.13.42.png" alt=""></p>
<p>아래를 보면 회원 로그인이 된 상태여서, <code>Post</code> Model에 새로운 게시글을 작성할 수 있게 되었다.</p>
<p><img src="https://images.velog.io/images/django_apps/post/8514cc70-037d-44ef-a8a7-92a6741801fc/Screen%20Shot%202021-09-19%20at%2015.14.57.png" alt=""></p>
<p>다음 포스팅에서는, 유저를 등록할 수 있는 화면을 간단히 구성해보고 이를 <code>Post</code> Model 등록 권한과 연계하면서 CRUD API를 만들어 보도록 하자.</p>
<p>Thank you!</p>
]]></description>
        </item>
        <item>
            <title><![CDATA[[Series1. DashBoard 만들기] - 6. Serializer 만들기 (1)]]></title>
            <link>https://velog.io/@django_apps/Series1-6</link>
            <guid>https://velog.io/@django_apps/Series1-6</guid>
            <pubDate>Sat, 18 Sep 2021 09:39:14 GMT</pubDate>
            <description><![CDATA[<blockquote>
<h3 id="serializer는-무엇인가">Serializer는 무엇인가?</h3>
</blockquote>
<p>  저번 시간에는 <code>Post</code> Table에 대한 View를 만들어서, 누구라도 data를 조회할 수 있도록 유저의 Request로 온 URL로 연결시켰다.</p>
<p>그러나, 서버를 가동시킨 후에 우리가 설정했던 URL <code>http://localhost:8000/posts/</code> 로 들어가보니 아래와 같이 에러가 나버린다.... -_-;;</p>
<p>↓ <code>Serializer</code> 가 존재하지 않는다고 에러가 난다.</p>
<p><img src="https://images.velog.io/images/django_apps/post/ac62398b-e6be-4c1e-aa83-234215ab1346/Screen%20Shot%202021-09-18%20at%2015.53.50.png" alt=""></p>
<p><img src="https://images.velog.io/images/django_apps/post/fb55d167-4b56-40db-968a-37aff4c5b05c/Screen%20Shot%202021-09-18%20at%2016.00.06.png" alt=""></p>
<p>..그렇다면 <code>Serializer</code>가 없으면 왜 에러가 날까?</p>
<p>일단 <code>Serailizer</code> 개념에 대해서 알아보자.</p>
<p>말 그대로 <code>직렬화</code> 라는 뜻인데, 크게 2가지 기능을 한다.</p>
<ol>
<li>유저에서 받아온 데이터를 <code>django</code> 에서 처리할 수 있는 (Python 언어가 다룰 수 있는) 데이터 형으로 변환해 주는 기능을 한다고 이해하면 된다.</li>
</ol>
<p><code>django</code> [Model, QuerySet, Instance...]  &lt;----&gt; <code>Content</code>[JSON, XML...]</p>
<ol start="2">
<li>보통 웹 애플리케이션은 유저에서 받은 데이터를 처리 한 후에, 서버가 유저의 화면에 뿌려 줄 데이터를 Response 객체와 함께 붙여서 유저에게 전송하는데 그때 보낼 데이터가 정의된 타입과 일치하는지 1차적으로 검증을 하는 역할을 한다.</li>
</ol>
<p>검증하는 법은, <code>Serializer</code> 클래스에 기본적으로 포함되어 있는 <code>is_valid()</code> 함수를 이용하면 되는데 다음 포스팅에서 더 알아볼 것이다. 지금은 개념만 이해하고 넘어가도록 하자.</p>
<p>지금까지 <code>Serializer</code> 의 기본적인 정의에 대해서 알아보았다.</p>
<p>간단히 유저에서 받은 데이터가 어떻게 유저에게 다시 돌려지는지 <code>django</code> 의 처리흐름을 정리하고 넘어가자.</p>
<blockquote>
<h3 id="django-에서의-데이터-처리-flow">django 에서의 데이터 처리 Flow</h3>
</blockquote>
<ol start="0">
<li><p><code>django</code> 서버에 Request가 들어옴</p>
</li>
<li><p><code>url.py</code> 에서 유저가 접속한 URL 주소를 파싱해서 해당하는 View를 호출한다</p>
</li>
<li><p>View에서 링크된 <code>DB Table</code> 에서 데이터를 가져온다</p>
</li>
<li><p>유저 요청에 따라 해당하는 <code>Python</code> 로직을 작성하여, 데이터를 가공한다. 필요에 따라서는 View를 이용해 <code>CRUD</code> 처리를 한다.</p>
</li>
<li><p>유저에게 전송하기 전에 <code>Serializer</code> 클래스로 데이터를 검증한다</p>
</li>
<li><p>유저에게 전송할 데이터를 클라이언트의 Content 타입(<code>JSON, XML..</code>)으로 <code>Serializer</code> 클래스를 사용해서 변환한다</p>
</li>
<li><p>유저에게 보낼 데이터를 Response 객체에 붙여서 같이 전송한다</p>
</li>
</ol>
<blockquote>
<h3 id="serializer를-정의하자">Serializer를 정의하자</h3>
</blockquote>
<p>이제 본격적으로, <code>Serializer</code> 를 정의하자.</p>
<p><code>dashbord_core</code> 폴더 안에서, <code>serializers.py</code> 파일을 생성하고 아래와 같이 작성하고 저장한다.</p>
<p><code>velog_series_01/dashboard/dashboard_core/serializers.py</code></p>
<pre><code class="language-python">from rest_framework import serializers
from dashboard_core.models import Post

class PostSerializer(serializers.ModelSerializer):
  title = serializers.CharField()
  contents = serializers.StringRelatedField()
  created_at = serializers.DateTimeField()

  class Meta:
    model = Post
    fields = &quot;__all__&quot;</code></pre>
<p>위 코드로 기본적인 <code>Post</code> Model에 대한 <code>Serializer</code> 클래스를 등록했으니 View에 연동시켜줘야 한다.</p>
<p>아래 코드 파일을 열고, <code>Serializer class</code> 를 추가해주자.
추가한 최종코드는 아래와 같다.</p>
<p><code>velog_series_01/dashboard/dashboard_core/views.py</code></p>
<pre><code class="language-python">from rest_framework.viewsets import ModelViewSet
from rest_framework.permissions import IsAuthenticatedOrReadOnly
from dashboard_core.models import Post
from dashboard_core.serializers import PostSerializer

# Create your views here.
class PostViewSet(ModelViewSet):
  queryset = Post.objects.all()
  serializer_class = PostSerializer
  permission_classes = [IsAuthenticatedOrReadOnly]
</code></pre>
<p>고생이 많으셨다.</p>
<p>이제 다시 서버를 올리고, <code>http://127.0.0.1:8000/</code> 에 접속해보자.</p>
<p><img src="https://images.velog.io/images/django_apps/post/0d3ff1c3-ecbb-47d3-a213-45c6d6271972/Screen%20Shot%202021-09-18%20at%2020.53.53.png" alt=""></p>
<p>저번 포스팅에서 등록했던 <code>Default Router</code> 의 메인 페이지가 표시된다.</p>
<p>자, 처음에 시도했었다 실패했었던 <code>http://127.0.0.1:8000/posts/</code> 에 접근해보자.</p>
<p><img src="https://images.velog.io/images/django_apps/post/1c57cf68-00b6-4baa-a42b-a6f95948305f/Screen%20Shot%202021-09-18%20at%2020.58.22.png" alt=""></p>
<p>위와 같이 에러없이 <code>Post</code> Model의 데이터 리스트 화면이 표시된다면, 성공한 것이다!</p>
<p>다음 포스팅에서는 <code>Serailizer</code> 까지 등록하였으니 본격적으로 데이터의 <code>CRUD</code> 처리를 확장시켜보자.</p>
<p>Thank you!</p>
]]></description>
        </item>
        <item>
            <title><![CDATA[[Series1. DashBoard 만들기] - 5. View 만들기 (1)]]></title>
            <link>https://velog.io/@django_apps/Series1-5</link>
            <guid>https://velog.io/@django_apps/Series1-5</guid>
            <pubDate>Fri, 17 Sep 2021 02:59:54 GMT</pubDate>
            <description><![CDATA[<blockquote>
<h3 id="post-model의-데이터를-조회하자">[Post] Model의 데이터를 조회하자!</h3>
</blockquote>
<p>  저번 포스팅에서는 <code>SuperUser</code> 를 만들어서, <code>django</code> 프로젝트 안에 속해 있는 Model에 접근해 보았다.</p>
<p>그러나, 관리자권한으로 로그인하지 않으면 Model의 데이터를 볼 수 없었기 때문에 모두에게 보여줄 수 없는 부분을 개선해야 한다.</p>
<p>오늘은 이 문제를<code>View</code>를 만들어서 해결해보자.</p>
<p><code>django</code>에서 <code>View</code>는 클라이언트에서 받은 요청에 따라 DB Tier (<code>Model</code>) 과 연결시켜서 필요한 데이터를 조회, 수정, 등록, 삭제하도록 중계하는 역할을 한다. </p>
<p>쉽게 말해서, 서버에서 데이터를 처리하는<code>로직</code> 부분이라 할 수 있다. </p>
<p>우리가 지금까지 DashBoard 프로젝트를 진행하면서 <code>Model</code> 과 <code>Admin</code> 만 생성했기 때문에, 데이터를 실제적으로 처리하고 클라이언트에게 돌려주는 부분이 없었다고 생각하면 된다.</p>
<p>자, 지금부터 본격적으로 <code>View</code>를 만들어 보자.
<code>velog_series_01/dashboard/dashboard_core/views.py</code> 를 코드 에디터로 열고 아래와 같이 작성하자.</p>
<pre><code class="language-python">from rest_framework.viewsets import ModelViewSet
from rest_framework.permissions import IsAuthenticatedOrReadOnly
from dashboard_core.models import Post

# Create your views here.
class PostViewSet(ModelViewSet):
  queryset = Post.objects.all()
  permission_classes = [IsAuthenticatedOrReadOnly]</code></pre>
<p><code>Post</code> Model 전용 View를 만들기 위해, <code>PostViewSet</code> 이라는 Python 클래스를 정의하는 코드이다.</p>
<p>이어서, 유저가 접근할 URL 패턴을 정의하자.
<code>velog_series_01/dashboard/dashboard/urls.py</code> 파일을 코드 에디터로 열고, 다음과 같이 작성하자.</p>
<pre><code class="language-python">from django.contrib import admin
from django.urls import include, path
from rest_framework.routers import DefaultRouter
from dashboard_core.views import PostViewSet

router = DefaultRouter()
router.register(r&quot;posts&quot;, PostViewSet, basename=&quot;post_status&quot;)

urlpatterns = [
    path(&#39;&#39;, include(router.urls)),
    path(&#39;admin/&#39;, admin.site.urls),
]
</code></pre>
<p>원래는 서버에 업로드 한 후에 <code>http://localhost:8000</code> 으로 접속하면 로켓 애니메이션이 표시되는 index 페이지로 다이렉트 하였으나, 그 부분을 우리가 만들었던 <code>Post</code> Model의 조회 페이지 <code>/posts</code> 로 보여주고 싶은 것이다.</p>
<p>여기까지 되었으면 기본적인 설정은 끝난 것이다.</p>
<p><code>django</code> 서버를 올린 다음, <code>http://localhost:8000</code> 으로 접속해보자.</p>
<p><img src="https://images.velog.io/images/django_apps/post/379fd4db-be5c-48b8-9810-aef2ccd85045/Screen%20Shot%202021-09-17%20at%2011.58.27.png" alt=""></p>
<p>다음과 같이 라우팅 설정이 되었음을 알 수 있다.</p>
<p>이어서 다음 포스팅에서는 본격적으로 Model의 Data를 보여주는 페이지를 만들어 보겠다.</p>
<p>Thank you!</p>
]]></description>
        </item>
    </channel>
</rss>