<?xml version="1.0" encoding="utf-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom">
    <channel>
        <title>dsts-01.log</title>
        <link>https://velog.io/</link>
        <description>초보 개발자의 테니스 과학적 분석 Dev-Log</description>
        <lastBuildDate>Thu, 19 Aug 2021 02:32:27 GMT</lastBuildDate>
        <docs>https://validator.w3.org/feed/docs/rss2.html</docs>
        <generator>https://github.com/jpmonette/feed</generator>
        <image>
            <title>dsts-01.log</title>
            <url>https://images.velog.io/images/dsts-01/profile/8fee4975-8bb3-4ca3-b55b-a9986bb63c71/social.png</url>
            <link>https://velog.io/</link>
        </image>
        <copyright>Copyright (C) 2019. dsts-01.log. All rights reserved.</copyright>
        <atom:link href="https://v2.velog.io/rss/dsts-01" rel="self" type="application/rss+xml"/>
        <item>
            <title><![CDATA[Ruby On Rails 이해하기 #4 (CRUD 에러노트)]]></title>
            <link>https://velog.io/@dsts-01/Ruby-On-Rails-%EC%9D%B4%ED%95%B4%ED%95%98%EA%B8%B0-4-CRUD-%EC%97%90%EB%9F%AC%EB%85%B8%ED%8A%B8</link>
            <guid>https://velog.io/@dsts-01/Ruby-On-Rails-%EC%9D%B4%ED%95%B4%ED%95%98%EA%B8%B0-4-CRUD-%EC%97%90%EB%9F%AC%EB%85%B8%ED%8A%B8</guid>
            <pubDate>Thu, 19 Aug 2021 02:32:27 GMT</pubDate>
            <description><![CDATA[<h1 id="레일즈-crud-가능한-게시판-만들기-중-에러모음">레일즈 CRUD 가능한 게시판 만들기 중 에러모음</h1>
<h2 id="요약-">요약 ;</h2>
<ul>
<li>레일즈앱 만들기</li>
<li>컨트롤러 만들기</li>
<li>모델 만들기</li>
<li>index 뷰파일 만들기</li>
<li>create 액션만들어서 데이터 저장하기</li>
<li>show를 만들기</li>
<li>edit/update action만들기</li>
<li>delete action 만들기</li>
</ul>
<h2 id="에러노트">&lt;에러노트&gt;</h2>
<h3 id="post-모델이-없는-상태에서-post-데이터를-가져오려고-함">Post 모델이 없는 상태에서 Post 데이터를 가져오려고 함.</h3>
<pre><code class="language-ruby"># 에러발생
에러노트NameError in TestController#index
**uninitialized constant TestController::Post**

# 상황
def index
     @posts = Post.all
end</code></pre>
<h3 id="rake-dbmigrate-했더니-문제-이건-migrate에-title과-content가-인식되지-않는-문제">rake db:migrate 했더니 문제, 이건 migrate에 title과 content가 인식되지 않는 문제</h3>
<pre><code class="language-ruby">## 에러발생
rake aborted!
StandardError: An error has occurred, this and all later migrations canceled:

undefined method `title&#39; for #&lt;ActiveRecord::ConnectionAdapters::SQLite3::TableDefinition:0x00007f98467619a8&gt; /Users/ohsekwang/codestates/ruby/r_test/db/migrate/20210804065613_create_posts.rb:4:in`block in change&#39;
/Users/ohsekwang/codestates/ruby/r_test/db/migrate/20210804065613_create_posts.rb:3:in `change&#39;

Caused by:
NoMethodError: undefined method `title&#39; for #&lt;ActiveRecord::ConnectionAdapters::SQLite3::TableDefinition:0x00007f98467619a8&gt; /Users/ohsekwang/codestates/ruby/r_test/db/migrate/20210804065613_create_posts.rb:4:in`block in change&#39;
/Users/ohsekwang/codestates/ruby/r_test/db/migrate/20210804065613_create_posts.rb:3:in `change&#39;

# 문제해결
## mirate 파일에서 입력
### 수정 전
t.title :string
t.content :string

### 수정 후 
t.string :title #t.데이터 타입을 쓰고, :params로 넘겨줄 이름을 쓴다.
t.string :content</code></pre>
<h3 id="라우트-에러--routesrb에-post로-설정해놓고-newerb-파일에서-method를-get를-설정해-놓음">라우트 에러 : routes.rb에 post로 설정해놓고, new.erb 파일에서 method를 get를 설정해 놓음</h3>
<pre><code class="language-ruby"># 에러발생
Routing Error
No route matches [GET] &quot;/create&quot;

# 에러해결
## new.erb 파일 수정
&lt;form action=&quot;/create&quot; method=&quot;get&quot;&gt;
=&gt;  &lt;form action=&quot;/create&quot; method=&quot;post&quot;&gt;
</code></pre>
<h3 id="토큰-에러이고-이유는-보안문제이다-임시적으로-해결방법으로-해결">토큰 에러이고, 이유는 보안문제이다. 임시적으로 해결방법으로 해결</h3>
<pre><code class="language-ruby">## 에러발생
# ActionController::InvalidAuthenticityToken in PracticeController#result
**ActionController::InvalidAuthenticityToken**

## application_controller. rb 파일에 다음을 추가해준다.
skip_before_action :verify_authenticity_token, raise: false
skip_before_filter :verify_authenticity_token, :only =&gt; :create

버전 업되면서 사라짐 
=&gt; skip_before_action :verify_authenticity_token, :only =&gt; :create</code></pre>
<h3 id="객체-post에서--idpost_id-찾을-수-없다">객체 Post에서  id=:post_id 찾을 수 없다.</h3>
<pre><code class="language-ruby">## 에러 발생
ActiveRecord::RecordNotFound in TestController#show
Couldn&#39;t find Post with &#39;id&#39;=:post_id
Extracted source (around line #18):          

## controller에서 show action
  def show
      @post = Post.find(params[:post_id])
  end

문제해결
## index.erb 버튼에서 수정
&lt;% @posts.each do |post| %&gt; # 
  &lt;%= post.title %&gt; **&lt;a href=&quot;/show/:post.id&quot;&gt;article 보기&lt;/a&gt;**
  &lt;%= post.content %&gt; 
&lt;% end %&gt;

## 버튼의 부분을 수정
&lt;a href=&quot;/show/:post.id&quot;&gt;article 보기&lt;/a&gt;
=&gt;&lt;a href=&quot;/show/&lt;%=post.id %&gt;&quot;&gt;article 보기&lt;/a&gt;</code></pre>
<h3 id="에러--내용에-해당되는-데이터가-저장되지-않는-문제">에러 : 내용에 해당되는 데이터가 저장되지 않는 문제</h3>
<ul>
<li><p>에러 화면 이미지 캡쳐</p>
<p>  <img src="https://s3-us-west-2.amazonaws.com/secure.notion-static.com/2d517f83-411b-4344-8e80-4dd065ab4e26/Screen_Shot_2021-08-04_at_10.11.33_PM.png" alt="https://s3-us-west-2.amazonaws.com/secure.notion-static.com/2d517f83-411b-4344-8e80-4dd065ab4e26/Screen_Shot_2021-08-04_at_10.11.33_PM.png"></p>
</li>
</ul>
<pre><code class="language-ruby">## migrate 파일에서 파일명 확인
t.string :title
t.string **:content**

## new.erb에서 오타 발견
&lt;form action=&quot;/create&quot; method=&quot;post&quot;&gt;
  제목 :&lt;input type=&quot;text&quot; name=&quot;title&quot; /&gt; &lt;br /&gt;
  내용 :&lt;input type=&quot;text&quot; **name=&quot;centent&quot;** /&gt; &lt;br /&gt; 
  &lt;input type=&quot;submit&quot; /&gt;
&lt;/form&gt;

## 오타 해결
**=&gt; centent =&gt; content로**</code></pre>
<h3 id="에러-토큰-에러-보안문제-허용하는-것으로">에러: 토큰 에러, 보안문제, 허용하는 것으로</h3>
<pre><code class="language-ruby"># 문제발생
## ActionController::InvalidAuthenticityToken in TestController#update

**ActionController::InvalidAuthenticityToken**

## :create 하나만 있었는데, :update도 추가
### 수정전
skip_before_action :verify_authenticity_token, :only =&gt; :create
### 수정후
skip_before_action :verify_authenticity_token, :only =&gt; :create, **:update**

## 문법오류
SyntaxError
**/Users/ohsekwang/codestates/ruby/r_test/app/controllers/application_controller.rb:2: syntax error, unexpected &#39;\n&#39;, expecting =&gt;**
Extracted source (around line **#2**):

## application_controller에서 :update추가
### 수정전
skip_before_action :verify_authenticity_token, :only =&gt; **:create, :update**

### 수정후
=&gt;skip_before_action :verify_authenticity_token, :only =&gt; **[:create, :update]**</code></pre>
<h2 id="상황별-필기노트--에러노트">상황별 필기노트 &amp; 에러노트</h2>
<h3 id="레일즈앱-만들기">레일즈앱 만들기</h3>
<pre><code class="language-ruby"># 터미널 창에서 쓰기 
## 레일즈 앱 처음 만들기
rails new r_test
## r_test 폴더에 들어가기 
cd r_test</code></pre>
<h3 id="컨트롤러-만들기">컨트롤러 만들기</h3>
<pre><code class="language-ruby"># 터미널 창에서 test 컨트롤러 만들기
rails g controller test

#VS코드를 실행시키기

## test_controller.rb 파일에서 index 액션 만들기
def index
end

## views의 index.erb 만들기
</code></pre>
<h3 id="에러-발생--post-모델이-없는-상태에서-post-데이터를-가져오려고-함">에러 발생 : Post 모델이 없는 상태에서 Post 데이터를 가져오려고 함.</h3>
<pre><code class="language-ruby"># 에러발생
에러노트NameError in TestController#index
**uninitialized constant TestController::Post**

# 상황
def index
     @posts = Post.all
end

## 문제해결 모델 만듦</code></pre>
<h3 id="모델-만들기">모델 만들기</h3>
<pre><code class="language-ruby"># 터미널에서 모델 만들기
rails g model Post

## VS코드에서 config폴더에서 migrate 파일를 열고, 데이터 스키마 만들기
t.string :title
t.string :content

#터미널 창에서 DB를 migrate 쓰기
rake db:migrate</code></pre>
<h3 id="에러발생--rake-dbmigrate-했더니-문제-이건-migrate에-title과-content가-인식되지-않는-문제">에러발생 : rake db:migrate 했더니 문제, 이건 migrate에 title과 content가 인식되지 않는 문제</h3>
<pre><code class="language-ruby">## 에러발생
rake aborted!
StandardError: An error has occurred, this and all later migrations canceled:

undefined method `title&#39; for #&lt;ActiveRecord::ConnectionAdapters::SQLite3::TableDefinition:0x00007f98467619a8&gt; /Users/ohsekwang/codestates/ruby/r_test/db/migrate/20210804065613_create_posts.rb:4:in`block in change&#39;
/Users/ohsekwang/codestates/ruby/r_test/db/migrate/20210804065613_create_posts.rb:3:in `change&#39;

Caused by:
NoMethodError: undefined method `title&#39; for #&lt;ActiveRecord::ConnectionAdapters::SQLite3::TableDefinition:0x00007f98467619a8&gt; /Users/ohsekwang/codestates/ruby/r_test/db/migrate/20210804065613_create_posts.rb:4:in`block in change&#39;
/Users/ohsekwang/codestates/ruby/r_test/db/migrate/20210804065613_create_posts.rb:3:in `change&#39;

# 문제해결
## mirate 파일에서 입력
### 수정 전
t.title :string
t.content :string

### 수정 후 
t.string :title #t.데이터 타입을 쓰고, :params로 넘겨줄 이름을 쓴다.
t.string :content</code></pre>
<h3 id="index-뷰파일-만들기-중">index 뷰파일 만들기 중</h3>
<pre><code class="language-ruby">index 뷰파일 실행 안됨
&lt;% @posts.each do |post| %&gt; # 
  &lt;%= post.title %&gt;
  &lt;%= post.content %&gt; 
&lt;% end %&gt;

## create action을 만들지 않아 데이터 저장이 안됨
</code></pre>
<h3 id="create-만들어서-데이터-저장하기">create 만들어서 데이터 저장하기</h3>
<pre><code class="language-ruby">#컨트롤러에서 액션 만들기
def create
      post = Post.new
      post.title = params[:title]
      post.content = params[:content]
      post.save
      redirect_to &#39;/&#39;
end

## routes.rb 추가
post &#39;/create&#39; =&gt; &#39;test#create&#39;

## new.erb 파일 수정
&lt;form action=&quot;/&quot; method=&quot;get&quot;&gt; 
=&gt;  &lt;form action=&quot;/create&quot; method=&quot;get&quot;&gt;
</code></pre>
<h3 id="라우트-에러--routesrb에-post로-설정해놓고-newerb-파일에서-method를-get를-설정해-놓음-1">라우트 에러 : routes.rb에 post로 설정해놓고, new.erb 파일에서 method를 get를 설정해 놓음</h3>
<pre><code class="language-ruby"># 에러발생
Routing Error
No route matches [GET] &quot;/create&quot;

# 에러해결
## new.erb 파일 수정
&lt;form action=&quot;/create&quot; method=&quot;get&quot;&gt;
=&gt;  &lt;form action=&quot;/create&quot; method=&quot;post&quot;&gt;
</code></pre>
<h3 id="에러노트---토큰-에러이고-이유는-보안문제이다-임시적으로-해결방법으로-해결">에러노트 :  토큰 에러이고, 이유는 보안문제이다. 임시적으로 해결방법으로 해결</h3>
<pre><code class="language-ruby">## 에러발생
# ActionController::InvalidAuthenticityToken in PracticeController#result
**ActionController::InvalidAuthenticityToken**

## application_controller. rb 파일에 다음을 추가해준다.
skip_before_action :verify_authenticity_token, raise: false
skip_before_filter :verify_authenticity_token, :only =&gt; :create

버전 업되면서 사라짐 
=&gt; skip_before_action :verify_authenticity_token, :only =&gt; :create</code></pre>
<h3 id="show를-만들기-중">show를 만들기 중</h3>
<pre><code class="language-ruby"># index에서 show article 버튼 만들기
&lt;a href=&quot;/show/:post_id&quot;&gt;article 보기&lt;/a&gt;

## controller show action
def show
     @post = Post.find(params[:post_id])
end

# routes.rb
get &#39;/show/:post_id&#39; =&gt; &#39;test#show&#39;

## show.erb
주제:&lt;%= @post.title %&gt; &lt;br&gt;
내용:&lt;%= @post.content %&gt; &lt;hr&gt;
</code></pre>
<h3 id="에러--객체-post에서--idpost_id-찾을-수-없다">에러 : 객체 Post에서  id=:post_id 찾을 수 없다.</h3>
<pre><code class="language-ruby">## 에러 발생
ActiveRecord::RecordNotFound in TestController#show
Couldn&#39;t find Post with &#39;id&#39;=:post_id
Extracted source (around line #18):          

## controller에서 show action
  def show
      @post = Post.find(params[:post_id])
  end

문제해결
## index.erb 버튼에서 수정
&lt;% @posts.each do |post| %&gt; # 
  &lt;%= post.title %&gt; **&lt;a href=&quot;/show/:post.id&quot;&gt;article 보기&lt;/a&gt;**
  &lt;%= post.content %&gt; 
&lt;% end %&gt;

## 버튼의 부분을 수정
&lt;a href=&quot;/show/:post.id&quot;&gt;article 보기&lt;/a&gt;
=&gt;&lt;a href=&quot;/show/&lt;%=post.id %&gt;&quot;&gt;article 보기&lt;/a&gt;
</code></pre>
<h3 id="에러--내용에-해당되는-데이터가-저장되지-않는-문제-1">에러 : 내용에 해당되는 데이터가 저장되지 않는 문제</h3>
<ul>
<li><p>에러 화면 이미지 캡쳐</p>
<p> <img src="https://images.velog.io/images/dsts-01/post/4e6ab3d4-a12c-457d-a4ef-f1d41f17a914/%E1%84%8C%E1%85%A5%E1%84%8C%E1%85%A1%E1%86%BC%E1%84%83%E1%85%AC%E1%84%8C%E1%85%B5%20%E1%84%8B%E1%85%A1%E1%86%AD%E1%84%82%E1%85%B3%E1%86%AB.png" alt=""></p>
</li>
</ul>
<pre><code class="language-ruby">## migrate 파일에서 파일명 확인
t.string :title
t.string **:content**

## new.erb에서 오타 발견
&lt;form action=&quot;/create&quot; method=&quot;post&quot;&gt;
  제목 :&lt;input type=&quot;text&quot; name=&quot;title&quot; /&gt; &lt;br /&gt;
  내용 :&lt;input type=&quot;text&quot; **name=&quot;centent&quot;** /&gt; &lt;br /&gt; 
  &lt;input type=&quot;submit&quot; /&gt;
&lt;/form&gt;

## 오타 해결
**=&gt; centent =&gt; content로**</code></pre>
<h2 id="edit-만들기">edit 만들기</h2>
<pre><code class="language-ruby">##index.erb 수정버튼
&lt;a href=&quot;/edit/&lt;%=post.id %&gt;&quot;&gt;article 수정&lt;/a&gt; &lt;br /&gt;

## controller edit 액션만들기
def edit
      @post = Post.find(params[:post_id])
end

## edit.erb 파일
&lt;form action=&quot;/update/&lt;%=@post.id%&gt;&quot; method=&quot;post&quot;&gt; #update액션에 연결되도록
  &lt;input type=&quot;text&quot; name=&quot;title&quot; value=&quot;&lt;%=@post.title%&gt;&quot; /&gt;
  &lt;input type=&quot;text&quot; name=&quot;content&quot; value=&quot;&lt;%=@post.title%&gt;&quot; /&gt;
  &lt;input type=&quot;submit&quot; /&gt;
&lt;/form&gt;

## controller update 추가
def update
      post = Post.find(params[:post_id])
      post.title = params[:title]
      post.content = params[:content]
      post.save
      redirect_to :back =&gt; redirect_back(fallback_location: root_path)
  end

## routes.rb edit와 update url과 action 연결
get &#39;/edit/:post_id&#39; =&gt; &#39;test#edit&#39;
post &#39;/update/:post_id&#39; =&gt; &#39;test#update&#39;
</code></pre>
<h3 id="에러-토큰-에러-보안문제-허용하는-것으로-1">에러: 토큰 에러, 보안문제, 허용하는 것으로</h3>
<pre><code class="language-ruby"># 문제발생
## ActionController::InvalidAuthenticityToken in TestController#update

**ActionController::InvalidAuthenticityToken**

## :create 하나만 있었는데, :update도 추가
### 수정전
skip_before_action :verify_authenticity_token, :only =&gt; :create
### 수정후
skip_before_action :verify_authenticity_token, :only =&gt; :create, **:update**

## 문법오류
SyntaxError
**/Users/ohsekwang/codestates/ruby/r_test/app/controllers/application_controller.rb:2: syntax error, unexpected &#39;\n&#39;, expecting =&gt;**
Extracted source (around line **#2**):

## application_controller에서 :update추가
### 수정전
skip_before_action :verify_authenticity_token, :only =&gt; **:create, :update**

### 수정후
=&gt;skip_before_action :verify_authenticity_token, :only =&gt; **[:create, :update]**</code></pre>
<h3 id="delete액션-만들기-중">delete액션 만들기 중</h3>
<pre><code class="language-ruby">## controller에서 delete action 만들기
def delete
        Post.destroy(params[:post_id)
        redirect_to &#39;/&#39;
end
## index.erb
&lt;a herf=&#39;/delete/&lt;%=post.id %&gt;&#39;&gt;article삭제 &lt;/a&gt;

## routes.rb
get &#39;/delete/:post_id&#39; =&gt; &#39;test#delete&#39;</code></pre>
]]></description>
        </item>
        <item>
            <title><![CDATA[Ruby On Rails 이해하기 #3  (CRUD 이해하기)]]></title>
            <link>https://velog.io/@dsts-01/Ruby-On-Rails-%EC%9D%B4%ED%95%B4%ED%95%98%EA%B8%B0-3-CRUD-%EC%9D%B4%ED%95%B4%ED%95%98%EA%B8%B0</link>
            <guid>https://velog.io/@dsts-01/Ruby-On-Rails-%EC%9D%B4%ED%95%B4%ED%95%98%EA%B8%B0-3-CRUD-%EC%9D%B4%ED%95%B4%ED%95%98%EA%B8%B0</guid>
            <pubDate>Thu, 19 Aug 2021 02:25:30 GMT</pubDate>
            <description><![CDATA[<h1 id="생성-읽기-업데이트-삭제-등을-이해한다">생성, 읽기, 업데이트, 삭제 등을 이해한다.</h1>
<h2 id="키워드--마이그레이션-파일-dbrake-action-method">키워드 : 마이그레이션 파일, db:rake, action, method,</h2>
<h2 id="요약-">요약 :</h2>
<h3 id="모델">&lt;모델&gt;</h3>
<ul>
<li>모델을 만들기 ⇒ 어떤 데이터 타입으로 저장할 지, 하는 것!</li>
<li>뷰 페이지에서, form으로 url, method 설정</li>
<li>모델 마이그레이션<ul>
<li>실제 데이터를 저장할 때, 데이터 타입, 데이터 이름, 공개 여부 등을 다 설정해줘야 한다.</li>
</ul>
</li>
</ul>
<h3 id="데이터의-흐름">&lt;데이터의 흐름&gt;</h3>
<ul>
<li>모델을 만들어서, 저장할 데이터 타입과 이름을 설정해준다.</li>
<li>config의 migrate 파일을 수정한다.</li>
<li>db를 migrate한다.</li>
<li>뷰 페이지에서 사용자로부터 입력받은 데이터가 처리되도록 설정해준다.</li>
</ul>
<h3 id="실습">실습</h3>
<pre><code class="language-python">
# 글을 생성하는 페이지와 read 페이지를 만든다. 
## controller에 create action 추가
## view file에 create.erb 추가
## routes.rb URL과 액션 추가

# 우선 모델을 만든다. 
rails g model Post

# form 태그 페이지
&lt;a href=&quot;/practice/index&quot;&gt;list post&lt;/a&gt;

&lt;form action=&quot;/practice/create&quot; method=&quot;post&quot;&gt;
  제목: &lt;input type=&quot;text&quot; name=&quot;title&quot; /&gt; &lt;br /&gt;
  내용 : &lt;input type=&quot;text&quot; name=&quot;content&quot; /&gt;&lt;br /&gt;
  &lt;input type=&quot;submit&quot; /&gt;
&lt;/form&gt;</code></pre>
<h2 id="모델-생성">모델 생성</h2>
<h3 id="키워드--each-do--create-param">키워드 : each do , create, param</h3>
<h3 id="요약--1">요약 :</h3>
<ul>
<li>모델 생성<ul>
<li>migrate 파일 데이터 타입설정</li>
<li>db 마이그레이트</li>
</ul>
</li>
<li>create<ul>
<li>views create 정보입력받을 폼 만들기</li>
<li>controller action 만들기 create</li>
<li>routes.rb url, 액션연결하기</li>
</ul>
</li>
<li>index<ul>
<li>정보 목록 보일 views 파일 수정</li>
</ul>
</li>
</ul>
<h3 id="필기노트">필기노트</h3>
<pre><code class="language-python">#  모델 생성
rails g model Post

## DB -&gt; migrate 폴더에 파일 생김
t.string :title
t.text :content

# 모델 쓰기
rake db:migrate

## controller에서 create 액션에 기록 코드 저장
def create
    post = Post.new
    post.title = params[:title]
    post.content = parmas[:content]
    post.save
        redirect_to &#39;/practice/index&#39;
end

## index에 모든 생성된 글을 보여주는 목록을 만든다. 
&lt;%= @posts.each do |post| %&gt; 
  &lt;%= @post.title %&gt; &lt;br&gt;
  &lt;%= @post.content %&gt; &lt;br&gt;
&lt;% end %&gt;
</code></pre>
<h2 id="update와-destory-이해">update와 destory 이해</h2>
<h3 id="키워드--redirect_to-url-redirect_to-back--edit-postfind">키워드 : redirect_to &quot;url&quot;, redirect_to :back , edit, Post.find</h3>
<h3 id="요약--2">요약 :</h3>
<ul>
<li>edit<ul>
<li>컨트롤러에서 edit액션만들기, 특정 글을 선택</li>
<li>view 파일은 create와 비슷하게, 다만 form의 action, method 다르게</li>
<li>routes.rb 설정, /:post_id</li>
</ul>
</li>
<li>수정버튼 만들기<ul>
<li>a 태그활용</li>
<li>view 파일설정</li>
<li>routes.rb 설정, /:post_id</li>
</ul>
</li>
<li>수정버튼 update 되도록 설정<ul>
<li>a 태그 액션 바꾸기</li>
</ul>
</li>
<li>필기노트</li>
</ul>
<h3 id="실습-1">실습</h3>
<h3 id="edit">edit</h3>
<pre><code>```
# routes.rb edit 추가

# controller edit 액션추가

# view edit.erb 추가
create와 동일 하게 만듦

# index.erb에 수정 버튼만들기
```</code></pre><h3 id="수정파일-만들기">수정파일 만들기</h3>
<pre><code>```
# controller edit action에서 수정
def edit
    @post = Post.find(params[:post_id])
end

## routes.rb 에서 url로 post_id정보를 전달
get &#39;/practice/edit&#39; =&gt; &#39;practice#edit&#39;

## edit.erb 저장

&lt;form action=&quot;/practice/create&quot; method=&quot;post&quot;&gt;
  제목: &lt;input type=&quot;text&quot; name=&quot;title&quot; /&gt; &lt;br /&gt;
  내용 : &lt;input type=&quot;text&quot; name=&quot;content&quot; /&gt;&lt;br /&gt;
  &lt;input type=&quot;submit&quot; /&gt;
&lt;/form&gt;
```</code></pre><h3 id="수정버튼-만들어서-수정-처리하기">수정버튼 만들어서 수정 처리하기</h3>
<pre><code>```

# index.erb 파일에 수정버튼 만들기
&lt;a href=&quot;/practice/edit&quot;&gt; 글수정&lt;/a&gt;&lt;br /&gt;

# 컨트롤러에서 데이터 베이스에서 데이터 찾아서 채워주기
edit action
@post = Post.find(params[:post_id])

## routes.rb 수정 :post_id 정보 담아서 보내주도록
get &#39;/practice/edit/:post_id&#39; =&gt; &#39;practice#edit&#39;

## index.erb 파일에서 post.id를 가져오도록 설정
&lt;a href=&quot;/practice/edit/&lt;%=post.id %&gt;&quot;&gt; 

## edit.erb 파일 수정! 인스턴스변수 post를 가져와서 title,content를 가져온다. 
value=&quot;&lt;%=@post.title%&gt;&quot;/&gt; 
value=&quot;&lt;%=@post.content%&gt;&quot;/&gt;
```</code></pre><h3 id="수정한-내용을-저장한다">수정한 내용을 저장한다.</h3>
<pre><code>```
# 컨트롤러에서 update 액션만들기
def update
      @post = Post.find(params[:post_id])
      post.title = params[:title]
      post.content = params[:content]
      post.save
      redirect_to &#39;/practice/index&#39;
end

## edit.erb 수정
&lt;form action=&quot;/practice/update/&lt;%=@post.id%&gt;&quot; method=&quot;post&quot;&gt;

## 에러발생
NameError in PracticeController#update
undefined local variable or method `post&#39; for #&lt;PracticeController:0x00000000011af8&gt;

## update에서는 edit action 처럼 @인스턴스 변수를 쓸 필요가 없다. 그 이유는 인스턴스 변수로, view 파일로 넘겨줄필요가 없기 때문이다. 

def update
      post = Post.find(params[:post_id])
      post.title = params[:title]
      post.content = params[:content]
      post.save
      redirect_to &#39;/practice/index&#39;
end
```</code></pre><h3 id="삭제하기">삭제하기</h3>
<pre><code>```
# 컨트롤러에 delete action 만들기
def delete
    Post.destroy(params[:post_id])
    redirect_to :back
end

# routes.rb에 연결해주기
get &#39;/practice/delete/:post_id&#39; =&gt; &#39;practice#delete&#39;

# index.erb에 삭제버튼 만들기
&lt;a href=&#39;/practice/delete/&lt;%= post.id%&gt;&#39;&gt;delete &lt;/a&gt;

## redirect_to 대신에
redirect_back fallback_location: &#39;practice/index&#39;
```</code></pre>]]></description>
        </item>
        <item>
            <title><![CDATA[Ruby On Rails 이해하기 #2 (Get/Post 이해하기)]]></title>
            <link>https://velog.io/@dsts-01/Ruby-On-Rails-%EC%9D%B4%ED%95%B4%ED%95%98%EA%B8%B0-2-GetPost-%EC%9D%B4%ED%95%B4%ED%95%98%EA%B8%B0</link>
            <guid>https://velog.io/@dsts-01/Ruby-On-Rails-%EC%9D%B4%ED%95%B4%ED%95%98%EA%B8%B0-2-GetPost-%EC%9D%B4%ED%95%B4%ED%95%98%EA%B8%B0</guid>
            <pubDate>Thu, 19 Aug 2021 01:56:46 GMT</pubDate>
            <description><![CDATA[<h1 id="어떻게-정보를-담아서-보낼-것인가">어떻게 정보를 담아서 보낼 것인가?</h1>
<h2 id="키워드--get-post-param-request-form-method-action-type-name">키워드 : get, post, param, request, form, method, action, type, name</h2>
<h2 id="요약-">요약 :</h2>
<ul>
<li>get/post로 정보를 전달할 수 있다.</li>
<li>레일즈에서의 정보전달 방법<ul>
<li>form 태그는 정보를 묶어서 보내는 태그<ul>
<li>method 어떤 방식으로 정보를 전달할지? get/post 등등</li>
<li>action 어디로 정보를 전달할지 ? url 주소</li>
</ul>
</li>
<li>input 정보를 받는 태그<ul>
<li>type 어떤 종류의 정보를 받을지? string, float?</li>
<li>name 정보의 이름 ? 전화번호? 생년월일?</li>
</ul>
</li>
</ul>
</li>
</ul>
<h3 id="데이터를-보내는-방법-3가지">데이터를 보내는 방법 3가지</h3>
<h3 id="주소창에서-사용">&lt;주소창에서 사용&gt;</h3>
<pre><code class="language-ruby">#URL주소창에서
/?dev=sekwang #dev는 키, sekwang은 실제 데이터

#rails에서는 params라는 메소드를 활용해서만 그 데이터를 쓸 수 있다.

## controller에서는 dev 데이터를 보기 위해서는 params 데이터에 볼 수 있다. 
name = params[:dev] # 이렇게 변수에 담아서 쓸 수 있다.

## 계산기를 만든다고 생각해보면

### routes.rb에서
get &#39;/sum&#39; =&gt; &#39;home#sum&#39;

### controller에서
def sum
     @first = params[:first].to_i
     @second = params[:second].to_i
     @sum = @first+@second
end

### view
&lt;%= @first%&gt; + &lt;%=@second%&gt; = &lt;%=@sum%&gt; 입니다.

### 주소창에서
/sum?first=10&amp;second=20</code></pre>
<h3 id="html-태그로-사용--a태그-form-태그">HTML 태그로 사용 : a태그, form 태그</h3>
<pre><code class="language-ruby"># a 태그
&lt;a herf=&#39;/?dev=sekwang&#39;&gt; 전송 &lt;a/&gt; 

## 버튼 누르면 주소로 이동, 포함되서 요청이 됨 =&gt; 쿼리스트링을 지정해서 사용하기 어렵다. 

#form 태그
&lt;form action=&quot;/sum&quot;&gt;
    &lt;input type=&quot;text&quot; name=&quot;first&quot;&gt;
    &lt;input type=&quot;text&quot; name=&quot;second&quot;&gt;
    &lt;button type=&quot;submit&quot;&gt;제출&lt;/button&gt;
&lt;/form&gt;
</code></pre>
<h3 id="데이터가-쿼리스트링으로는-데이터-pw-블로그글-처럼-길-때는-다른-방법-필요">데이터가 쿼리스트링으로는 데이터 PW, 블로그글 처럼 길 때는 다른 방법 필요.</h3>
<pre><code class="language-ruby">#form태그 에 method 추가 
## post저장할 데이터, 보안 
## a태그 쿼리 스트링, order, 필터, 개발자가 정해놓은 데이터가 넘겨야 할 때 정해 놓은동작 실행 
### form get 구글 검색기능을 구현할 때 많이 사용
&lt;form action=&quot;/sum&quot;, **method=&#39;post&#39;&gt; ## http 메소드란 서버에 주소를 요청을 보낼 때의 방식을 뜻함/ 기본값 get / post는** 
    &lt;input type=&quot;text&quot; name=&quot;first&quot;&gt;
    &lt;input type=&quot;text&quot; name=&quot;second&quot;&gt;
    &lt;button type=&quot;submit&quot;&gt;제출&lt;/button&gt;
&lt;/form&gt;

# routes. rb post 추가!
**post** &quot;sum&quot; =&gt; &quot;home#sum&quot;

#application controller 수정 추가
skip_before_action :verify_authenticity_token
</code></pre>
<h3 id="route-파라미터-path-파라미터-주소-자체-보내는-데이터를-포함시키는-방법--⇒-페이지를-불러오기-위해서-특정-값이-필수-일-때-쓴다">route 파라미터, path 파라미터 주소 자체 보내는 데이터를 포함시키는 방법!  ⇒ 페이지를 불러오기 위해서 특정 값이 필수 일 때 쓴다.</h3>
<pre><code class="language-ruby">##routes.rb :id가 path 파라미터
get &quot;home/:id&quot; =&gt; &quot;home#show&quot;

## home controller
def show 
    @id = params[:id]
end

## show.html.erb
id는 &lt;%= @id %&gt;

## 주소창에 값에 따라 달라짐 
/home/1 =&gt; id는 1
/home/sekwang =&gt; id는 sekwang
</code></pre>
<h3 id="home-컨트롤러에서-action에-show로-요청을-보내려면">home 컨트롤러에서 action에 show로 요청을 보내려면</h3>
<pre><code class="language-ruby"># get &quot;home/:id&quot; =&gt; &quot;home#show&quot; 
무조건 id데이터값이 필요함.

# 애초에 특정한 데이터를 필수적으로 받아야 하는 요청 페이지는

# path 파라미터 데이터 베이스, 모델과 연결지어 사용됨
## 특정데이터를 가져오는 로직으로 만들 것이다. 
</code></pre>
<h2 id="get과-post의-차이">get과 post의 차이</h2>
<p><img src="https://images.velog.io/images/dsts-01/post/b4345532-5fe8-42a7-b2e7-a4ec8e7b790a/get%E1%84%80%E1%85%AApost.png" alt=""></p>
<p>참조 : <a href="https://www.youtube.com/channel/UCtSgWEneJWFlSTkjHlBZlsA">https://www.youtube.com/channel/UCtSgWEneJWFlSTkjHlBZlsA</a></p>
]]></description>
        </item>
        <item>
            <title><![CDATA[Ruby On Rails 이해하기 #1 (MVC 패턴)]]></title>
            <link>https://velog.io/@dsts-01/Ruby-On-Rails-%EC%9D%B4%ED%95%B4%ED%95%98%EA%B8%B0-MVC-%ED%8C%A8%ED%84%B4-1</link>
            <guid>https://velog.io/@dsts-01/Ruby-On-Rails-%EC%9D%B4%ED%95%B4%ED%95%98%EA%B8%B0-MVC-%ED%8C%A8%ED%84%B4-1</guid>
            <pubDate>Thu, 19 Aug 2021 01:50:20 GMT</pubDate>
            <description><![CDATA[<h1 id="ruby-on-rails는-무엇인가">Ruby On Rails는 무엇인가?</h1>
<p>ruby 언어로 웹 프로그래밍을 빠르게 할 수 있는 프레임 워크이다. 2004년 오픈소스 프로젝트 시작 후 10년후 rails 4.2가 개발 되었고, 계속적으로 업데이트 되고 있다. </p>
<h2 id="rails-원칙">Rails 원칙</h2>
<h3 id="mvc-패턴">MVC 패턴</h3>
<p>M 모델 비즈니스 로직 데이터와 데이터 베이스 대한 작업하는 역할, V 사용차에 대한 요청 결과물, 화면에 표출되는 로직과 데이터를 다루는 역할 , C 모델과 뷰를 연결, 사용자의 입력을 받아 모델을 조작, 데이터의 흐름을 제어하는 역할로 나눠지고 있다. 이를 통해 서버로부터 데이터를 가져와서 브라우저 이용자에게 그 데이터를 보여주는 것까지의 패턴을 지니고 있다. </p>
<h3 id="cocconvention-over-configuration-설정보다-규칙">CoC(Convention over Configuration, 설정보다 규칙)</h3>
<p>최선의 방법으로 빠르게 개발 할 수 있게 rails way를 설정해 놓았다. 즉 개발자의 설정에 대한 고민을 줄이고, rails way로 빠르게 개발할 수 있도록 한 것이다. 이에 대해서는 개발자의 성향에 따라 논쟁이 있다.</p>
<h3 id="drydont-repeat-yourself-같은-코드-반복-하지-말자">DRY(Don&#39;t Repeat Yourself, 같은 코드 반복 하지 말자)</h3>
<p>같은 코드를 반복하지 않도록 디자인하였다. </p>
<h2 id="mvc-패턴-이해하기">MVC 패턴 이해하기</h2>
<h3 id="키워드--모델-뷰-컨트롤러">키워드 : 모델, 뷰, 컨트롤러</h3>
<h3 id="요약--">요약  :</h3>
<ul>
<li><p>모델 : 어플리케이션의 정보, 데이터를 다루는 규칙</p>
</li>
<li><p>뷰 : 데이터 표현을 관련하는 html,css 파일 관리</p>
</li>
<li><p>컨트롤러 : 모델과 뷰를 연결하고, url과 메소드 연결</p>
</li>
<li><p>필기노트 : MVC 패턴 이해, 모델과 뷰, 컨트롤러 각각의 역할 이해,</p>
</li>
</ul>
<p><img src="https://images.velog.io/images/dsts-01/post/4cf6a5e8-2288-4598-a40d-4d52f9e31124/railsmvc.png" alt=""></p>
<h3 id="브라우저에서-요청이-들어왔을-때-처리과정">브라우저에서 요청이 들어왔을 때 처리과정</h3>
<ul>
<li>routes.rb : 요청확인 → 회원정보 보여줘! ⇒ 브라우저가 보낸 URL과 controller에 액션을 연결</li>
<li>controller : 브라우저 요청 확인 → 모델과 연결 -&gt; 정보를 확인하고 view에 연결 </li>
</ul>
<h2 id="레일즈-동작원리-이해하기">레일즈 동작원리 이해하기</h2>
<h3 id="키워드--서버작동--컨트롤러-생성--루비코드-작성erb-파일에서">키워드 : 서버작동 , 컨트롤러 생성 , 루비코드 작성(erb 파일에서)</h3>
<h3 id="요약">요약</h3>
<ul>
<li>동적인 웹 이해하기</li>
<li>레일즈의 RCV 동작원리 이해하기</li>
</ul>
<h3 id="간단한-로직">간단한 로직</h3>
<ul>
<li>주소로 요청 분석(routes)</li>
<li>요청에 맞는 처리(컨트롤러 액션)</li>
<li>처리에 맞는 응답(view)</li>
</ul>
<p>동적인 요청과 응답사이에 RCV가 있어야 한다. 동적인 웹 페이지 html만들어진다.</p>
<h3 id="브라우저와-rails의-상호작용">브라우저와 rails의 상호작용</h3>
<ol>
<li>레일즈에서 컨트롤러를 만들기</li>
<li>controller파일에서 실행할 액션을 정의한다.</li>
<li>브라우저의 url주소 대응하는 컨트롤러 액션을 연결 ⇒ config 폴더의 routes.rb 파일에서 변경해준다.</li>
<li>컨트롤러 액션과 같은 이름의 view 파일이 생성하여, 브라우저의 보여줄 데이터를 css,html, 루비코드로 작성한다.</li>
</ol>
<p><img src="https://images.velog.io/images/dsts-01/post/1c699c7a-68c7-48c5-9823-c5d8bb5e65ea/railsrvc.png" alt=""></p>
<p>참조 : <a href="https://www.youtube.com/channel/UC_jdHCSOKZ66kQBwPp2CAgg">https://www.youtube.com/channel/UC_jdHCSOKZ66kQBwPp2CAgg</a></p>
]]></description>
        </item>
        <item>
            <title><![CDATA[클럽 랭킹 시스템 도입을 위한 데이터 기록 앱 개발기]]></title>
            <link>https://velog.io/@dsts-01/%ED%81%B4%EB%9F%BD-%EB%9E%AD%ED%82%B9-%EC%8B%9C%EC%8A%A4%ED%85%9C-%EB%8F%84%EC%9E%85%EC%9D%84-%EC%9C%84%ED%95%9C-%EB%8D%B0%EC%9D%B4%ED%84%B0-%EA%B8%B0%EB%A1%9D-%EC%95%B1-%EA%B0%9C%EB%B0%9C%EA%B8%B0</link>
            <guid>https://velog.io/@dsts-01/%ED%81%B4%EB%9F%BD-%EB%9E%AD%ED%82%B9-%EC%8B%9C%EC%8A%A4%ED%85%9C-%EB%8F%84%EC%9E%85%EC%9D%84-%EC%9C%84%ED%95%9C-%EB%8D%B0%EC%9D%B4%ED%84%B0-%EA%B8%B0%EB%A1%9D-%EC%95%B1-%EA%B0%9C%EB%B0%9C%EA%B8%B0</guid>
            <pubDate>Fri, 13 Aug 2021 11:52:03 GMT</pubDate>
            <description><![CDATA[<h2 id="페더러-영상을-보며-생각하다">페더러 영상을 보며, 생각하다.</h2>
<p>나는 페더러 선수를 좋아한다. 많은 사람들이 테니스 역사에서 최고의 선수라고 극찬한다. 그 이유는 바라보는 사람에 따라 다양할 것이다. 그 중 내 관점에서는 그가 가장 상황에 적확한 샷을 하기 때문에 좋아한다. 그는 자신의 샷을 선택할 때, 경기흐름과 상황을 파악하고, 상대방의 마음을 읽고, 그리고 자신이 가진 많은 샷과 패턴 중에서 공격포인트를 따기 좋은 것을 선택한다. 그 선택이 탁월하다. 그래서 상대선수로 예상하지 못하고, 해설자들도 감탄하는 샷을 날린다. 그의 경기를 볼 때면, 정말 상황에 적합한 샷을 구사한다는 생각이 든다. 어려운 샷이 아닌 어찌보면 쉽고 단순하지만 그 상황에서 득점포인트로 이어질 수 있는 최적의 샷을 계속하여 연구하고 만들어간다. 그것이 그의 테니스가 예술의 경지에 올랐다고 표현되는 이유일 것이다.
참조 영상 : <a href="https://www.youtube.com/watch?v=8LefyKfXUtg">https://www.youtube.com/watch?v=8LefyKfXUtg</a></p>
<h2 id="기술에-압도-당하기-보다-이-기술이-어떤-문제를-해결할-수-있을까">&quot;기술에 압도 당하기 보다 이 기술이 어떤 문제를 해결할 수 있을까?&quot;</h2>
<p>&quot;데이터를 기술로 보지 말고, 문제해결의 수단으로 생각하라&quot;라는 메세지는 굉장히 강렬했다. 배우기에 생소하고 어렵다고 느끼는 기술을 그 어려움에 압도당하지 않고, 어떤 문제를 해결할 수 있는 문제해결의 수단으로 어떻게 활용할 지 생각하며 대하려 노력했다. 그렇게 버티며 꾸준히 해 나가다 보니, 기능 하나 하나 구현하며 재미를 느꼈고, 에러 메세지를 만났을 때 일종의 선물 보따리를 하나씩 꺼내서 받는 느낌으로 변해 갔다. 그렇게 문제를 해결하기 위해 기술을 어떻게 사용할 지 고민해 나갔다.
참조영상 : <a href="https://www.youtube.com/watch?v=4BhmpyDK5j8">https://www.youtube.com/watch?v=4BhmpyDK5j8</a></p>
<h3 id="테니스-실력을-객관적으로-나타내기-위해-지금-무엇부터-해야할까">&quot;테니스 실력을 객관적으로 나타내기 위해 지금 무엇부터 해야할까?&quot;</h3>
<p>앞의 2개의 블로그 글에서 언급한 것처럼 테니스의 실력을 <strong>&#39;감&#39;의 영역에서 &#39;데이터&#39; 영역으로 바꾸기 위해 고민했고 여러가지를 참조하였다.</strong> 그 과정에서 가장 중요한 것은 실력의 판단기준이 될 수 있는 데이터를 먼저 쌓는 것이었다. 실력을 가늠할 수 있는 데이터를 선택하고 그 데이터를 지속적으로 쌓아나가는 것이 먼저 필요했다. 매달 열리는 월례회 데이터를 쌓고, 그 데이터를 등록하고, 조회하고, 그 데이터에 일정 포인트를 도입해서 랭킹 포인트를 부여하는 방식으로 생각해 나갔다. 즉, 실력을 입증할 수 있는 데이터를 꾸준히 쌓고, 그 데이터를 조회할 수 있고, 그 데이터에 일정한 랭킹을 부여하기 위해서 랭킹 포인트를 부여하는 방식을 채택해 보았다.</p>
<h2 id="플라스크를-활용하여-간단한-웹앱을-만들기">플라스크를 활용하여 간단한 웹앱을 만들기</h2>
<p><img src="https://images.velog.io/images/dsts-01/post/166d5ffc-720b-4805-9ca1-4cee4ca70f3f/Flask.png" alt="">
참조 : <a href="https://flask.palletsprojects.com/en/1.1.x/">https://flask.palletsprojects.com/en/1.1.x/</a></p>
<h3 id="플라스크flask는-무엇인가">플라스크(flask)는 무엇인가?</h3>
<p>플라스크는 마이크로 웹 프레임워크이다. 웹 프레임워크는 웹 앱을 개발하는데, 필요한 작업들을 세부적인 작업들을 처리해줘서 웹을 개발하는데, 수월하게 도와준다. 플라스크는 파이썬의 다른 웹 프레임워크인 장고에 비해 패키지가 가볍고, 설정해야하는 것들이 상대적으로 적어서 빠르고 가볍게 웹을 만들 수 있는 장점이 있다. 파이썬의 또 다른 프레임 워크인장고와 비슷한 루비 온 레일즈 프레임워크와 써 봤을 때, MVC 패턴으로 DB, Controller, View파일을 관리하고, 그 구조로 이해해서 개발하는 것이 익숙했던 나에게는 flask가 처음에는 좀 생소하게 다가왔다. 그래서 그 구조를 이해하는데 좀 시간이 걸렸던 것 같다. 하지만, 직접 써봤을 때 미리 사전에 많은 컨벤션(convention)을 알고, 내부적으로 작동하는 원리를 이해하기 전까지 구조를 파악하기 어려운 장고와 같은 프레임워크에 비해, 플라스크가 짧은 시간 안에 이해하고, 개발하기에 용이했다.
플라스크 SQL알카미(Flask-SQLAlchemy)를 활용하다
웹 앱을 개발할 때, 플라스크 SQL알카미 활용하였다. 웹앱을 개발할 때 데이터 베이스(DB)와 상호작용하기 위해서는 SQL쿼리문을 활용해야 한다(SQL 데이터 베이스일 경우). 이 쿼리문으로 데이터베이스에 저장된 데이터를 조회하고, 저장하고, 삭제하고, 업데이트 등 다양한 것들을 실행시킨다. 그런데 파이썬 언어를 활용하여 개발을 진행하다가 SQL쿼리문을 써야하는 불편함을 겪에 된다. 이 때 파이썬 언어로 SQL쿼리문을 실행할 수 있는 SQL알카미를 활용할 수 있다.
Flask-SQLAlchemy는 ORM(Object Relational Mapper) 중 하나이다. ORM은 데이터베이스와 상호작용할 때, 파이썬과 같은 언어로 개발할 때 친숙한 클래스와 메소드 등을 활용하여 데이터베이스를 제어할 수 있게 해주는 것이다. 즉, 자신이 개발하고 있는 언어를 활용하여 따로 SQL쿼리문을 활용하지 않고, 개발언어 자체로 데이터베이스를 제어할 수 있도록 도와주는 것이다. 이렇게 하면 개발과정이 조금 더 수월해진다. 그리고 클래스와 메소드를 이용하여 코드를 관리하기도 편리해지는 장점이 있다.</p>
<h3 id="플라스크-sql알카미flask-sqlalchemy를-활용하다">플라스크 SQL알카미(Flask-SQLAlchemy)를 활용하다</h3>
<p>웹 앱을 개발할 때, 플라스크 SQL알카미 활용하였다. 웹앱을 개발할 때 데이터 베이스(DB)와 상호작용하기 위해서는 SQL쿼리문을 활용해야 한다(SQL 데이터 베이스일 경우). 이 쿼리문으로 데이터베이스에 저장된 데이터를 조회하고, 저장하고, 삭제하고, 업데이트 등 다양한 것들을 실행시킨다. 그런데 파이썬 언어를 활용하여 개발을 진행하다가 SQL쿼리문을 써야하는 불편함을 겪에 된다. 이 때 파이썬 언어로 SQL쿼리문을 실행할 수 있는 SQL알카미를 활용할 수 있다.</p>
<p><strong>Flask-SQLAlchemy</strong>는 ORM(Object Relational Mapper) 중 하나이다. ORM은 데이터베이스와 상호작용할 때, 파이썬과 같은 언어로 개발할 때 친숙한 클래스와 메소드 등을 활용하여 데이터베이스를 제어할 수 있게 해주는 것이다. 즉, 자신이 개발하고 있는 언어를 활용하여 따로 SQL쿼리문을 활용하지 않고, 개발언어 자체로 데이터베이스를 제어할 수 있도록 도와주는 것이다. 이렇게 하면 개발과정이 조금 더 수월해진다. 그리고 클래스와 메소드를 이용하여 코드를 관리하기도 편리해지는 장점이 있다.</p>
<h2 id="데이터를-저장-조회-삭제-수정-랭킹포인트를-부여할-수-있는-웹앱">데이터를 저장, 조회, 삭제, 수정, 랭킹포인트를 부여할 수 있는 웹앱</h2>
<p><img src="https://images.velog.io/images/dsts-01/post/f2450614-0405-413f-9d37-a782d445d365/%E1%84%83%E1%85%A6%E1%84%8B%E1%85%B5%E1%84%90%E1%85%A5%20db.png" alt=""></p>
<p>위의 그림과 같이 routes폴더와 templates 폴더를 만들어서 관리한다.
routes폴더는 실제 사용자가 입력하는 URL주소와 model파일, view 파일간의 상호작용할 수 있도록 일종의 가이드 역할을 해준다. 아래의 그림과 같이, 각 URL 주소에 따라 서로 다른 페이지를 보여준다. 그리고 그 페이지에서 입력되거나 처리된 파일들을 DB와 상호작용하여 저장하고, 삭제하고, 조회하도록 컨트롤 한다. 그 일련의 과정을 어떻게 해야할 지 이 폴더의 파일들을 관리한다.
templates 폴더에서는 각각의 웹 페이지에서 사용자에게 보여줄 화면을 어떻게 구성할지 코드로 구현해 놓은 파일들을 모아 둔다. 사용자가 URL주소를 입력하면, 그에 해당하는 view파일을 불러와서, 사용자에게 그 화면을 보여준다. 즉routes의 파일들과 URL를 통해 상호작용할 때 사용자에게 보여줄 view파일을 관리한다.</p>
<h3 id="화면구성">화면구성</h3>
<p><img src="https://images.velog.io/images/dsts-01/post/e90bdf5f-2c8c-41c9-94e7-c14ac346e174/image.png" alt=""></p>
<p><img src="https://images.velog.io/images/dsts-01/post/f35f6cd3-4629-42e3-a8cb-421ef9955ea6/image.png" alt=""></p>
<p><img src="https://images.velog.io/images/dsts-01/post/b0758661-3a93-4189-9a67-836b75f352b0/image.png" alt=""></p>
<h2 id="실제-웹앱의-기능">실제 웹앱의 기능</h2>
<p>우선 메인 페이지에는 실제 경기한 기록들이 나타난다. 대회 종류, 월례회 일정, 이긴 선수들, 진 선수들, 획득한 게임수 등을 나타내준다.</p>
<p><img src="https://images.velog.io/images/dsts-01/post/c9f31812-2b77-4a6d-9e59-be05746a9ca5/image.png" alt=""></p>
<p>다음으로 이런 월례회 결과를 입력할 수 있는 페이지가 있다. 대회 종류, 월례회 일정, 이긴 선수들, 진 선수들, 획득한 게임수를 입력하여 저장할 수 있다.</p>
<p><img src="https://images.velog.io/images/dsts-01/post/150e5499-1fe7-4aee-bbe5-ab628b804603/image.png" alt=""></p>
<p>그리고 이렇게 입력한 정보들 중 자신의 결과를 알아보고 싶으면 조회할 수 있다. 아래와 같이 자신의 이름을 입력한 후 GET 버튼을 누르면, 자신의 경기 결과만 조회해볼 수 있다.</p>
<p><img src="https://images.velog.io/images/dsts-01/post/c27d7bf2-0ebf-4d32-9e9e-9bc657b0e699/image.png" alt=""></p>
<p>그런데 만약 입력한 결과 값이 실수로 인해 다르게 입력되었을 경우, 수정할 수 있다. 예를 들어 위에 3번째 경기의 winner2의 이름과 loser1의 이름 그리고 Num of loser game이 수정해야할 경우 아래와 같이 수정할 수 있다.</p>
<p><img src="https://images.velog.io/images/dsts-01/post/964ebdce-0b05-4895-b93e-06452da85ead/image.png" alt=""></p>
<p>그리고 각 경기에 대한 결과를 바탕으로 랭킹 포인트를 부여하여, 자신의 이름을 입력하면 랭킹 포인트를 확인할 수 있다.</p>
<p><img src="https://images.velog.io/images/dsts-01/post/5fc9a73a-1911-45c0-9d36-7aaa4bbfed17/image.png" alt=""></p>
<h1 id="에러의-대한-두려움이-많이-사라지다">에러의 대한 두려움이 많이 사라지다</h1>
<p><img src="https://images.velog.io/images/dsts-01/post/4804cabb-2e57-4824-aa68-d8092dcd1fb7/image.png" alt=""></p>
<p>참조영상 : <a href="https://www.youtube.com/watch?v=xBG4xGX6D_Q">https://www.youtube.com/watch?v=xBG4xGX6D_Q</a></p>
<p>이번 프로젝트를 통해서 가장 크게 느낀 것은 에러에 대한 두려움이 많이 사라졌다는 것이다. 새로운 기능을 추가할 때 만나는 에러를 조금 더 담담하게, 그리고 일종의 선물을 받는 것처럼 느끼려고 노력했던 시간이었다. 그리고 작은 기능하나가 구현되었을 때 느끼는 희열감도 느낄 수 있었다. 에러가 발생하는 것이 문제가 아니라 그 에러를 두려워하는 나의 마음의 문제임을 느꼈던 시간이었다. 매 공마다 최선을 다하는 흙신 라파엘 나달의 말처럼, 에러에 두려워하는 나의 마음을 다 잡을 수 있었던 시간이었다.</p>
]]></description>
        </item>
        <item>
            <title><![CDATA[관계형 데이터 베이스 #3]]></title>
            <link>https://velog.io/@dsts-01/%EA%B4%80%EA%B3%84%ED%98%95-%EB%8D%B0%EC%9D%B4%ED%84%B0-%EB%B2%A0%EC%9D%B4%EC%8A%A4-3</link>
            <guid>https://velog.io/@dsts-01/%EA%B4%80%EA%B3%84%ED%98%95-%EB%8D%B0%EC%9D%B4%ED%84%B0-%EB%B2%A0%EC%9D%B4%EC%8A%A4-3</guid>
            <pubDate>Fri, 13 Aug 2021 09:30:12 GMT</pubDate>
            <description><![CDATA[<h1 id="관계형-데이터-베이스">관계형 데이터 베이스</h1>
<h2 id="왜-관계형-데이터-베이스를-배워야-하는가">왜 관계형 데이터 베이스를 배워야 하는가?</h2>
<h3 id="스프레드-시트와-비교-데이터가-중복된다면-중복을-제거하여-사용가능">스프레드 시트와 비교 (데이터가 중복된다면 중복을 제거하여 사용가능)</h3>
<p><img src="https://images.velog.io/images/dsts-01/post/d55c56b8-818a-4ea0-b0a6-1ca1eac9370d/%E1%84%89%E1%85%B3%E1%84%91%E1%85%B3%E1%84%85%E1%85%A6%E1%84%83%E1%85%B3%E1%84%89%E1%85%B5%E1%84%90%E1%85%B3%20%E1%84%87%E1%85%B5%E1%84%80%E1%85%AD.png" alt=""></p>
<p>참조 : 생활코딩 데이터베이스</p>
<h3 id="저자들의-정보를-따로-뺌">저자들의 정보를 따로 뺌.</h3>
<p><img src="https://images.velog.io/images/dsts-01/post/12813a77-f053-43d7-acd7-e2a0dee5d5b4/%E1%84%83%E1%85%A6%E1%84%8B%E1%85%B5%E1%84%90%E1%85%A5%E1%84%87%E1%85%A6%E1%84%8B%E1%85%B5%E1%84%89%E1%85%B3%20%E1%84%8C%E1%85%A5%E1%84%8C%E1%85%A1%E1%84%8C%E1%85%A5%E1%86%BC%E1%84%87%E1%85%A9.png" alt=""></p>
<h3 id="topic정보-author_id를-부여하여-중복이-사라짐">topic정보 author_id를 부여하여 중복이 사라짐.</h3>
<p><img src="https://images.velog.io/images/dsts-01/post/e240fcb3-92a5-4f41-bca9-5293d8e22dca/topic%E1%84%8C%E1%85%A5%E1%86%BC%E1%84%87%E1%85%A9.png" alt=""></p>
<h3 id="author_id로-식별가능해진다">author_id로 식별가능해진다.</h3>
<p><img src="https://images.velog.io/images/dsts-01/post/39859420-8da3-4712-850a-528a1bbfcba9/%E1%84%8C%E1%85%A5%E1%84%8C%E1%85%A1id.png" alt=""></p>
<h3 id="장점이-생겼지만-단점이-생긴-부분">장점이 생겼지만, 단점이 생긴 부분</h3>
<p>하나의 테이블은 한눈에 직관적으로 판단가능. 하지만 중복을 제거 못함.</p>
<p>테이블을 두개로 쪼갰을 때, 비교해서 표를 확인해야하는 문제가 생김.</p>
<h3 id="별도의-테이블로-보관하여-중복이-없으면서도-하나의-표로-확인하고-싶어진다">별도의 테이블로 보관하여 중복이 없으면서도, 하나의 표로 확인하고 싶어진다.</h3>
<h2 id="에러노트--auto_increment를-사용한-columns은">에러노트 : AUTO_INCREMENT를 사용한 columns은</h2>
<p><img src="https://images.velog.io/images/dsts-01/post/a29e0201-e98e-46ac-addb-2f97430f0ffe/%E1%84%8B%E1%85%A6%E1%84%85%E1%85%A5%E1%84%82%E1%85%A9%E1%84%90%E1%85%B31.png" alt=""></p>
<pre><code class="language-python">
## 에러 발생 코드
CREATE TABLE author(
        id INT NOT NULL AUTO_ICREMENT, 
        name VARCHAR(100) NOT NULL, 
        profile TEXT NULL);

## AUTO_ICREMENT를 설정한 columns은 PRIMARY KEY로 설정해야한다.

## 해결코드
CREATE TABLE author(
        id INT NOT NULL AUTO_ICREMENT, 
        name VARCHAR(100) NOT NULL, 
        profile TEXT NULL,
        PRIMARY KEY(id));</code></pre>
<h3 id="auto_icrement를-설정한-columns은-primary-key로-설정해야한다">AUTO_ICREMENT를 설정한 columns은 PRIMARY KEY로 설정해야한다.</h3>
<h3 id="에러노트--작은-따옴표-하지-않았을-때">에러노트 : 작은 따옴표 하지 않았을 때</h3>
<p><img src="https://images.velog.io/images/dsts-01/post/129ac656-6bfc-4030-b188-8202eaaaec29/%E1%84%8B%E1%85%A6%E1%84%85%E1%85%A5%E1%84%82%E1%85%A9%E1%84%90%E1%85%B32.png" alt=""></p>
<pre><code class="language-python">## 에러 발생 코드
INSERT INTO author (name, profile) VALUES(michael, data sciendtist); 

## 따옴표 추가
INSERT INTO author (name, profile) VALUES(&#39;michael&#39;, &#39;data sciendtist&#39;); </code></pre>
<h3 id="테이블에-칼럼추가">테이블에 칼럼추가</h3>
<pre><code class="language-python">ALTER TABLE topic ADD author_id INT;

UPDATE topic SET author_id=2 WHERE id=3;</code></pre>
<h3 id="테이블을-합쳐서-보기">테이블을 합쳐서 보기</h3>
<pre><code class="language-python">## topic과 author 테이블을 합치는데, 기준은 topic의 author_id와 author의 id로 합친다.
SELECT * FROM topic LEFT JOIN author ON topic.author_id = author.id</code></pre>
<p><img src="https://images.velog.io/images/dsts-01/post/a7800128-a0a6-4b26-9691-e5b633b8b167/%E1%84%90%E1%85%A6%E1%84%8B%E1%85%B5%E1%84%87%E1%85%B3%E1%86%AF%20%E1%84%92%E1%85%A1%E1%86%B8%E1%84%8E%E1%85%B5%E1%84%80%E1%85%B5.png" alt=""></p>
<h1 id="테이블-분리">테이블 분리</h1>
<h3 id="테이블-네임-바꾸기">테이블 네임 바꾸기!</h3>
<pre><code class="language-python">## 새로운 이름 하기! 
RENAME TABLES topic TO topic_backup
</code></pre>
<h1 id="join">JOIN</h1>
<p>topic 테이블의 author_id의 값과 author 테이블의 id값을 붙여봐</p>
<pre><code class="language-python"># topic 테이블 확인
SELECT * FROM topic;

#author 테이블 확인
SELECT * FROM author;

# topic 테이블의 author_id와 author 테이블의 id를 기준으로 테이블을 합쳐서 보여줘
SELECT * FROM topic LEFT JOIN author ON topic.author_id = author.id</code></pre>
<p><img src="https://images.velog.io/images/dsts-01/post/cb23dcac-9277-48e6-aa04-269c2d456e45/Join.png" alt=""></p>
<h2 id="에러노트3">에러노트3</h2>
<h3 id="중복된-걸-없애주고-보이도록-한다">중복된 걸 없애주고 보이도록 한다.</h3>
<p><img src="https://images.velog.io/images/dsts-01/post/002bb6e1-4294-4e1b-bf9a-0d4d44ec9bdd/%E1%84%8B%E1%85%A6%E1%84%85%E1%85%A5%E1%84%82%E1%85%A9%E1%84%90%E1%85%B33.png" alt=""></p>
<p>에러 발생: 애매 모호 하다ㅏ. 왜냐하면 topic id와 author id가 중복되기 때문이다. </p>
<pre><code class="language-python">## 에러 발생코드
SELECT id,title,description,created,name,profile  FROM topic LEFT JOIN author ON topic.author_id = author.id;

## 에러 해결 코드
SELECT topic.id,title,description,created,name,profile  FROM topic LEFT JOIN author ON topic.author_id = author.id;

## id의 값을 topic_id라는 값으로 변환하여 보여주기
SELECT topic.id AS topic_id,title,description,created,name,profile  FROM topic LEFT JOIN author ON topic.author_id = author.id;
</code></pre>
<p><img src="https://images.velog.io/images/dsts-01/post/4d519bba-d59f-42c9-ac02-b7130dfdf05e/%E1%84%92%E1%85%A2%E1%84%80%E1%85%A7%E1%86%AF.png" alt=""></p>
<h2 id="중복은-없앤다는-것이-중요한-의미">중복은 없앤다는 것이 중요한 의미!</h2>
<p><img src="https://images.velog.io/images/dsts-01/post/8fcfb0d0-3b43-485f-8fd1-e40aea2f2e2f/%E1%84%8C%E1%85%AE%E1%86%BC%E1%84%87%E1%85%A9%E1%86%A8%E1%84%8B%E1%85%B3%E1%86%AF%20%E1%84%8B%E1%85%A5%E1%86%B9%E1%84%8B%E1%85%A2%E1%84%82%E1%85%B3%E1%86%AB%20%E1%84%80%E1%85%A5%E1%86%BA.png" alt=""></p>
<p>위에 테이블처럼 짜놓으면, 다 바꾸어야 함. </p>
<p>그런데 아래 테이블 처럼 분리한다면 유기적으로 연결되기 때문에, 자동으로 변화될 것이다. </p>
<p>Join을 통해 관계 가능.</p>
<h3 id="comment-테이블-만들기">comment 테이블 만들기</h3>
<pre><code class="language-python">create table comment (
    -&gt; id int(11) not null auto_increment,
    -&gt; description varchar(130) null,
    -&gt; author_id int(11) null,
    -&gt; primary key (id)
    -&gt; );</code></pre>
<h3 id="comment를-쓴-사람이-누구인지-보고싶다">comment를 쓴 사람이 누구인지 보고싶다.</h3>
<pre><code class="language-python">## 코멘트 확인
SELECT * FROM comment&#39;

## author 확인
SELECT * FROM author;

## comment와 author를 결합하여 확인
SELECT * FROM comment LEFT JOIN author ON comment.author_id = author.id;

## 정렬하여 확인
SELECT comment.id AS comment_id, description, name, profile FROM comment LEFT JOIN author ON comment.author_id = author.id;</code></pre>
<p><img src="https://images.velog.io/images/dsts-01/post/9c2aec92-a61b-4440-a801-7a45e4898dd1/%E1%84%92%E1%85%A2%E1%84%80%E1%85%A7%E1%86%AF2.png" alt=""></p>
]]></description>
        </item>
        <item>
            <title><![CDATA[데이터 베이스 기본문법 SQL #2]]></title>
            <link>https://velog.io/@dsts-01/%EB%8D%B0%EC%9D%B4%ED%84%B0-%EB%B2%A0%EC%9D%B4%EC%8A%A4-%EA%B8%B0%EB%B3%B8%EB%AC%B8%EB%B2%95-SQL-2</link>
            <guid>https://velog.io/@dsts-01/%EB%8D%B0%EC%9D%B4%ED%84%B0-%EB%B2%A0%EC%9D%B4%EC%8A%A4-%EA%B8%B0%EB%B3%B8%EB%AC%B8%EB%B2%95-SQL-2</guid>
            <pubDate>Fri, 13 Aug 2021 07:49:18 GMT</pubDate>
            <description><![CDATA[<h1 id="1-왜-데이터-베이스가-생겨-났을까">1. 왜 데이터 베이스가 생겨 났을까?</h1>
<p>File에서 벗어나 전문적인 소프트웨어 개발 1960년대부터</p>
<p>1970년 IBM 관계형 데이터 베이스를 만들었다. </p>
<p>데이터를 표의 형태로 검색을 빠르고 편리하고 안전하게 가능하다.</p>
<h2 id="my-sql">My SQL</h2>
<p>오픈 소스 </p>
<p>웹이 폭발적으로 성장하면서, 데이터 베이스 찾게 됨.</p>
<p>자연스럽게 mySQL를 사용하면서 동반성장을 하게 됨.</p>
<h1 id="2-데이터-베이스의-목적">2. 데이터 베이스의 목적</h1>
<h2 id="스프레드-시트와-데이터-베이스의-차이">스프레드 시트와 데이터 베이스의 차이</h2>
<p>스프레스 시트에서 필터로 정렬가능하다.</p>
<p>데이터 베이스는 컴퓨터 언어를 통해서 제어가 가능하다.</p>
<pre><code class="language-python">토픽에서 author 라는 행에서 sekwang이라는 것만 찾아줘 
SELECT * FROM topic WHERE author = &#39;sekwang&#39;;

id가 큰 수부터 해줘! 
SELECT * FROM topic WHERE author = &#39;sekwang&#39; ORDER BY id DESC;
</code></pre>
<h3 id="왜-컴퓨터-언어를-통해서-데이터를-제어할-수-있는-것이-중요한가">왜 컴퓨터 언어를 통해서 데이터를 제어할 수 있는 것이 중요한가?</h3>
<p>데이터 베이스를 통해 저장된 것, 웹, 앱으로 공유가능, 인공지능으로 분석 가능하다. </p>
<h1 id="3-mysql-설치">3. MySQL 설치</h1>
<h2 id="데이터-베이스의-구조">데이터 베이스의 구조</h2>
<p>연관된 표들을 고통</p>
<p>표에 저장이 된다.</p>
<p>연관된 데이터를 그룹핑하는 것 ⇒ 스키마 
<img src="https://images.velog.io/images/dsts-01/post/ec61b9f0-4dd2-495a-8621-139d95781179/MySQL%E1%84%89%E1%85%A5%E1%86%AF%E1%84%8E%E1%85%B5.png" alt=""></p>
<p>이미지참조: 생활코딩</p>
<h3 id="데이터-베이스의-효용">데이터 베이스의 효용</h3>
<ol>
<li>자체적인 보안체계, 데이터 안전하게 보관 가능</li>
<li>권한기능, 여러 사람을 등록하여, 데어터 접근 권한을 차등적으로 줄 수 있다. </li>
</ol>
<h1 id="4-스키마">4. 스키마</h1>
<h3 id="데이터-베이스-생성">데이터 베이스 생성</h3>
<pre><code class="language-python"># 데이터 베이스 생성
CREATE DATABASE &#39;데이터베이스명&#39;;

# 데이버 베이스 삭제
DROP DATABASE &#39;데이터베이스명&#39;;

# 데이버 베이스 확인
SHOW DATABASES;

# 데이터 베이스 사용하기
USE &#39;데이터베이스명&#39;;
## 핵심은 검색해서 하나씩 찾으면 된다.</code></pre>
<h1 id="5-sql과-테이블">5. SQL과 테이블</h1>
<h2 id="sql">SQL</h2>
<p><strong>S</strong>tructured, 정리정돈</p>
<p><strong>Q</strong>uery, 요청한다, 질의한다.</p>
<p><strong>L</strong>anguage, 공통의 약속, 언어</p>
<p>SQL 쉽고 중요하다.</p>
<ol>
<li>어떤 컴퓨터 언어보다도 쉽다. html,sql</li>
<li>중요하다.</li>
</ol>
<h2 id="용어정리">용어정리</h2>
<h3 id="table">table</h3>
<p>수평 : row, record 행 ⇒ 데이터 자체</p>
<p>수직 : columns, 열 ⇒ 데이터의 구조</p>
<p><img src="https://images.velog.io/images/dsts-01/post/71f789cb-17a0-4386-b9db-f8d01a0583d9/%E1%84%8F%E1%85%A1%E1%86%AF%E1%84%85%E1%85%A5%E1%86%B7%E1%84%92%E1%85%A2%E1%86%BC%E1%84%80%E1%85%AA%E1%84%8B%E1%85%A7%E1%86%AF.png" alt="">
참조: 생활코딩</p>
<h2 id="table-생성">table 생성</h2>
<p>create table in mysql cheat sheet</p>
<p><a href="https://devhints.io/mysql">https://devhints.io/mysql</a></p>
<h3 id="입력값을-규제한다">입력값을 규제한다.</h3>
<p>id 값은 숫자로 결정해 놓는다. </p>
<pre><code class="language-python">## 테이블 만들기 id 생성 칼럼이름, 데이터 타입, 보여줄것
CREATE TABLE topic(
    -&gt; id INT(11) NOT NULL AUTO_INCREMENT, # 값이 없는 걸 허용하지 않겠다. / 자동으로 ID값 생성
    -&gt; title VARCHAR(100) NOT NULL,
        -&gt; description TEXT NULL,
    -&gt; created DATATIME NOT NULL,
    -&gt; author VARCHAR(30) NULL,
    -&gt; profile VARCHAR(100) NULL,
    -&gt; PRIMARY KEY(id)

PRIMARY KEY는 고유한 값을 가지는 것! </code></pre>
<p>에러 노트</p>
<p>첫번째 에러</p>
<p><img src="https://images.velog.io/images/dsts-01/post/d35f657d-1416-42c9-9d5b-19e0d75fbbe8/SQL%20%E1%84%8E%E1%85%A5%E1%86%BA%E1%84%87%E1%85%A5%E1%86%AB%E1%84%8D%E1%85%A2%20%E1%84%8B%E1%85%A6%E1%84%85%E1%85%A5.png" alt=""></p>
<p>두번째 에러</p>
<p><img src="https://images.velog.io/images/dsts-01/post/b595d85d-3b61-4baa-9916-c14f6797d0b6/SQL%20%E1%84%83%E1%85%AE%E1%84%87%E1%85%A5%E1%86%AB%E1%84%8C%E1%85%A2%20%E1%84%8B%E1%85%A6%E1%84%85%E1%85%A5.png" alt=""></p>
<pre><code class="language-python">두 철자 에러가 발생하여 에러가 발생했다.

CREATE TABLE topic(
id INT(11) NOT NULL **AUTO INCREMENT**, 
title VARCHAR(100) NOT NULL, 
description TEXT NULL, 
created **DATATIME** NOT NULL, 
author VARCHAR(30) NULL, 
profile VARCHAR(100) NULL, 
PRIMARY KEY(id));

두개를 수정해주고 정상적으로 작동하였다. 
**AUTO INCREMENT =&gt; AUTO_INCREMENT**
**DATATIME =&gt; DATETIME**</code></pre>
<p><img src="https://images.velog.io/images/dsts-01/post/41fd033b-0edb-4891-a855-9062fc4838e3/SQL%20%E1%84%89%E1%85%B5%E1%86%AF%E1%84%92%E1%85%A2%E1%86%BC.png" alt=""></p>
<h3 id="새로운-비밀번호를-입력할-때">새로운 비밀번호를 입력할 때</h3>
<pre><code class="language-python">SET PASSWORD = PASSWORD(&#39;변경할 비밀번호&#39;)</code></pre>
<h1 id="7-crud">7. CRUD</h1>
<h2 id="insert생성">INSERT(생성)</h2>
<pre><code class="language-python"># mysql 접속
./mysql -uroot -p

# 데이터 베이스를 보기
SHOW DATABASES;

# 데이터 베이스를 사용하기
USE &#39;데이터베이스명&#39;

# 데이터 베이스의 테이블 보기
SHOW TABLES;

# 테이블의 구조 확인
DESC &#39;테이블명&#39;;
DESC topic

# 데이터 베이스의 테이블에 값을 추가한다. 
INSERT INTO &#39;테이블명&#39; (title,description,created,author,profile) VALUES(&#39;MySQL&#39;,&#39;MySQL is ....&#39;,NOW(),&#39;michael&#39;,&#39;Data Scientist&#39;)

# 현재시간 작성됨
NOW()</code></pre>
<h2 id="select선택--mysql-select-syntax">SELECT(선택) : mysql select syntax</h2>
<pre><code class="language-python">
# 추가된 데이터 베이스 보기
SELECT * FROM topic;

# 각각 칼럼들을 확인
SELECT title, id, description, created, author, profile FROM topic;

# 필요한 데이터가 가져오고 싶을 때
WHERE author = &#39;작가명&#39;

# 정렬하기 
ORDER BY id DESC;

# 제한을 걸어서 몇개 볼지 생각
LIMIT 2;</code></pre>
<h2 id="update">UPDATE</h2>
<pre><code class="language-python"># topic 테이블에서 title 칼럼에서 &#39;oracle&#39;인 데이터를 id 순서 대로, 2개만 가져와라!
SELECT * FROM topic WHERE title=&#39;oracle&#39; ORDER BY id DESC LIMIT 2;

# UPDATE하기 
## topic 테이블의 id=3에서 title 칼럼을 &#39;MySQL&#39;로 수정하고, description 칼럼은 &#39;MySQL is ...&#39;으로 수정한다.
UPDATE topic SET title=&#39;MySQL&#39;, description=&#39;MySQL is ...&#39; WHERE id=3;</code></pre>
<h2 id="delect">DELECT</h2>
<pre><code class="language-python"># DELETE FROM topic WHERE 

## topic 테이블의 title이 oracle인 것 삭제
DELETE FROM topic WHERE title=&#39;oracle&#39;;</code></pre>
]]></description>
        </item>
        <item>
            <title><![CDATA[# 데이터 베이스 #1
]]></title>
            <link>https://velog.io/@dsts-01/%EB%8D%B0%EC%9D%B4%ED%84%B0-%EB%B2%A0%EC%9D%B4%EC%8A%A4-1</link>
            <guid>https://velog.io/@dsts-01/%EB%8D%B0%EC%9D%B4%ED%84%B0-%EB%B2%A0%EC%9D%B4%EC%8A%A4-1</guid>
            <pubDate>Fri, 13 Aug 2021 07:43:38 GMT</pubDate>
            <description><![CDATA[<h2 id="데이터-베이스">데이터 베이스</h2>
<ul>
<li>안전하고, 편리하고, 빠르게 사용 가능</li>
<li>다양한 DB가 있음</li>
</ul>
<h2 id="데이터-베이스의-본질">데이터 베이스의 본질</h2>
<p>어떻게 입력하고 출력하는지를 아는 것이 중요하다. </p>
<h3 id="데이터-베이스의-핵심적인-작업">데이터 베이스의 핵심적인 작업</h3>
<ul>
<li>데이터 입력 : Create, Update, Delete</li>
<li>데이터 출력 : Read</li>
</ul>
<h2 id="file-vs-database">File vs Database</h2>
<h3 id="파일의-한계점">파일의 한계점</h3>
<p>작성자, 날짜, 본문 등 정렬을 할 수 없다.</p>
<p><img src="https://images.velog.io/images/dsts-01/post/562ae0b1-b28e-4d7e-ba7f-ea2a2c84ce31/%E1%84%91%E1%85%A1%E1%84%8B%E1%85%B5%E1%86%AF%E1%84%92%E1%85%A1%E1%86%AB%E1%84%80%E1%85%A8.png" alt=""></p>
<h3 id="스프레드-시트로-해결">스프레드 시트로 해결</h3>
<ul>
<li>하지만  구조를 먼저 작성한다.</li>
<li>제목, 본문, 작성일, 저자, 소개</li>
<li>저자별로, 필터로 확인할 수 있다.</li>
<li>구조적으로 데이터를 입력하니 훨씬 편함</li>
</ul>
<p><img src="https://images.velog.io/images/dsts-01/post/d84d9e21-4ace-4796-8b26-a8254eabc44f/%E1%84%89%E1%85%B3%E1%84%91%E1%85%B3%E1%84%85%E1%85%A6%E1%84%83%E1%85%B3%E1%84%89%E1%85%B5%E1%84%90%E1%85%B3.png" alt=""></p>
<h2 id="데이터-베이스로-가면">데이터 베이스로 가면</h2>
<ul>
<li>프로그래밍적으로, 컴퓨터 언어로 데이터를 추가하고, 수정,삭제, 읽을 수 있다.</li>
<li>하지만 전문적인 DB 소프트웨어들은 가지고 자동화할 수 있다.</li>
<li>이것이 스프레트 시트와의 차이이다.</li>
</ul>
]]></description>
        </item>
        <item>
            <title><![CDATA[# 어떻게 csv 파일로 chart.js 활용하여 시각화할 수 있을지?]]></title>
            <link>https://velog.io/@dsts-01/%EC%96%B4%EB%96%BB%EA%B2%8C-csv-%ED%8C%8C%EC%9D%BC%EB%A1%9C-chart.js-%ED%99%9C%EC%9A%A9%ED%95%98%EC%97%AC-%EC%8B%9C%EA%B0%81%ED%99%94%ED%95%A0-%EC%88%98-%EC%9E%88%EC%9D%84%EC%A7%80</link>
            <guid>https://velog.io/@dsts-01/%EC%96%B4%EB%96%BB%EA%B2%8C-csv-%ED%8C%8C%EC%9D%BC%EB%A1%9C-chart.js-%ED%99%9C%EC%9A%A9%ED%95%98%EC%97%AC-%EC%8B%9C%EA%B0%81%ED%99%94%ED%95%A0-%EC%88%98-%EC%9E%88%EC%9D%84%EC%A7%80</guid>
            <pubDate>Fri, 13 Aug 2021 07:32:44 GMT</pubDate>
            <description><![CDATA[<p>우선 csv 파일을 넣을 html 파일을 작성한다.</p>
<pre><code class="language-python">#test.html 파일에서

## 컨테이너를 만들어서 버튼을 만든다.
&lt;div class=&quot;container card&quot; style=&quot;...&quot;&gt;
  &lt;div class=&quot;row justify-content-center container&quot;&gt;
    &lt;div class=&quot;content&quot;&gt;
      &lt;h1&gt;csv 파일을 넣어주세요!&lt;/h1&gt;
      **&lt;form method=&quot;POST&quot; enctype=&quot;multipart/form-data&quot;&gt;
        {% csrf_token %}
        &lt;input type=&quot;file&quot; name=&quot;document&quot; id=&quot;document&quot; required=&quot;required&quot; /&gt;
        &lt;button id=&quot;submit&quot; class=&quot;btn-primary&quot;&gt;Upload&lt;/button&gt;
      &lt;/form&gt;**
    &lt;/div&gt;
  &lt;/div&gt;

## 파일을 업로드 할 수 있도록 버튼을 만든다. 
&lt;form method=&quot;POST&quot; enctype=&quot;multipart/form-data&quot;&gt;
    {% csrf_token %}
    &lt;input type=&quot;file&quot; name=&quot;document&quot; id=&quot;document&quot; required=&quot;required&quot; /&gt;
    &lt;button id=&quot;submit&quot; class=&quot;btn-primary&quot;&gt;Upload&lt;/button&gt;
&lt;/form&gt;
</code></pre>
<p><img src="https://images.velog.io/images/dsts-01/post/09098eb8-d7fb-4d9a-b682-189335df9a07/csv%20%E1%84%91%E1%85%A1%E1%84%8B%E1%85%B5%E1%86%AF%20%E1%84%87%E1%85%A5%E1%84%90%E1%85%B3%E1%86%AB.png" alt=""></p>
<h1 id="viewspy에서-함수를-만든다">views.py에서 함수를 만든다.</h1>
<pre><code class="language-python"># views.py

## test 함수를 정의한다.
def test(request):

    context={}     

    if request.method == &#39;POST&#39;: ## 제출했을 때 method가 작동
          uploaded_file = request.FILES**[&#39;document&#39;]** ## test.html의 id_name이름을 넣는다.

            **print(uploaded_file) ## 업로드 파일의 이름 보여줌.**

    return render(request, &#39;test.html&#39;)</code></pre>
<p><img src="https://images.velog.io/images/dsts-01/post/3e626db5-467d-4e89-b744-1b6c138abbc9/%E1%84%83%E1%85%A1%E1%84%8B%E1%85%AE%E1%86%AB%E1%84%85%E1%85%A9%E1%84%83%E1%85%B3.png" alt=""></p>
<p>atp_tennis_1998to2021.csv파일을 보여줌.</p>
<pre><code class="language-python"># views.py 파일
## 파일을 추가해주기 

from django.core.files.storage import FileSystemStorage ## 라이브러리를 가져오고

## csv 파일을 가져오고, save한다. 
if uploaded_file.name.endswith(&#39;.csv&#39;):
        #save to file in chartdata folder
        savefile = FileSystemStorage() ## 가져옴

                name = savefile.save(uploaded_file.name, uploaded_file) ## 이름과 파일
</code></pre>
<pre><code class="language-python"># views.py 파일
## 파일을 추가해주기 

#파일이 어디 있는지 안다.
      # courrent diretory of the project
        d = os.getcwd() 
        print(d)
        file_directory = d+&#39;\chartdata\\&#39;+name

        readfile(file_directory)

        return redirect(results)

      else: 
          messages.warning(request, &#39;파일이 제대로 업로드 되지 않았습니다!&#39;)


    return render(request, &#39;test.html&#39;)</code></pre>
<p>파일을 넣어주고, 리다이렉션 해준다. </p>
<h3 id="main-formspy를-추가해준다">main forms.py를 추가해준다.</h3>
<pre><code class="language-python">## forms.py

from django import forms

class UploadFileForm(forms.Form):
  title = forms.CharField(Max_length=50)
  file = forms.FileForm</code></pre>
<h3 id="resulthtml-파일을-만든다">result.html 파일을 만든다.</h3>
<pre><code class="language-python">from django.contrib import admin
from django.urls import path
from main.views import test,results,index

urlpatterns = [
    path(&#39;admin/&#39;, admin.site.urls),
    path(&#39;&#39;, index),
    **path(&#39;test/&#39;, test),
    path(&#39;results/&#39;, results)**
]</code></pre>
<p>urls.py파일에 추가해준다.</p>
<pre><code class="language-python"># views.py

from django.contrib import messages #메세지

## test 함수를 정의한다.
def test(request):

    context={}

    if request.method == &#39;POST&#39;:
      uploaded_file = request.FILES[&#39;document&#39;]

      print(uploaded_file)

      if uploaded_file.name.endswith(&#39;.csv&#39;):
        #save to file in chartdata folder
        savefile = FileSystemStorage()

        name = savefile.save(uploaded_file.name, uploaded_file) 


      #파일이 어디 있는지 안다.
      # courrent diretory of the project
        d = os.getcwd() 
        print(d)
        file_directory = d+&#39;\chartdata\\&#39;+name

        readfile(file_directory)

        **return redirect(results)

      else: 
          messages.warning(request, &#39;파일이 제대로 업로드 되지 않았습니다!&#39;)


    return render(request, &#39;test.html&#39;)**</code></pre>
<h2 id="판다스를-활용하여-파일-읽어오기">판다스를 활용하여 파일 읽어오기!</h2>
<pre><code class="language-python"># import pandas as pd 
## readfile 함수 만들기

def readfile(filename):

    my_file = pd.read_csv(filename, sep=&#39;[:;,|_]&#39;, engine = &#39;python&#39;)

    data = pd.DataFrame(data=my_file, index=None)

    print(data)</code></pre>
<h3 id="마이그레이션에서-에러-발생">마이그레이션에서 에러 발생</h3>
<pre><code class="language-python">## 오타문제

class UploadFileForm(forms.Form):
  title = forms.CharField**(max_length=50)**
  file = forms.FileForm</code></pre>
<p><img src="https://images.velog.io/images/dsts-01/post/39ddf0bb-80d8-4320-ba22-ecb0a21026e2/%E1%84%86%E1%85%A1%E1%84%8B%E1%85%B5%E1%84%80%E1%85%B3%E1%84%85%E1%85%A6%E1%84%8B%E1%85%B5%E1%84%89%E1%85%A7%E1%86%AB%20%E1%84%8B%E1%85%A9%E1%84%85%E1%85%B2%E1%84%87%E1%85%A1%E1%86%AF%E1%84%89%E1%85%A2%E1%86%BC.png" alt=""></p>
<h3 id="새로운-에러-발생">새로운 에러 발생</h3>
<p><img src="https://images.velog.io/images/dsts-01/post/89ec57f9-8d3d-4da2-9502-c03ed73c0691/%E1%84%89%E1%85%A2%E1%84%85%E1%85%A9%E1%84%8B%E1%85%AE%E1%86%AB%20%E1%84%8B%E1%85%A6%E1%84%85%E1%85%A5.png" alt=""></p>
<pre><code class="language-python">## **오타 문제**

from django import forms

class UploadFileForm(forms.Form):
  title = forms.CharField(max_length=50)
  **file = forms.FileField**
</code></pre>
<p>db파일 migrateion 제거 부터 다양한 에러 해결해보았지만, 해결되지 않음.</p>
<p>어떻게 해야할 지 고민</p>
<p><img src="https://images.velog.io/images/dsts-01/post/6dd904d2-9cc7-47fd-b337-232a22842ca4/%E1%84%8B%E1%85%A6%E1%84%85%E1%85%A5%E1%84%86%E1%85%A6%E1%84%89%E1%85%A6%E1%84%8C%E1%85%B5.png" alt=""></p>
<p>에러메세지 : file을 찾을 수 없다는 에러 메세지가 떴다. </p>
<p>에러발생</p>
<p><img src="https://images.velog.io/images/dsts-01/post/d65f201e-c730-41bc-8090-58246db42157/%E1%84%8B%E1%85%A6%E1%84%85%E1%85%A5%E1%84%86%E1%85%A6%E1%84%89%E1%85%A6%E1%84%8C%E1%85%B5%202.png" alt=""></p>
<h2 id="진행하면서-깨달은-점">진행하면서 깨달은 점</h2>
<p>데이터 베이스에 대한 개념을 이해하고 있지 못하다는 것을 깨달았다. 
그래서 데이터 베이스에 대한 개념을 이해하고 해결해야함을 느꼈다. </p>
]]></description>
        </item>
        <item>
            <title><![CDATA[테니스 빅3(페더러,나달,조코비치)의 그랜드 슬램 우승 횟수 확인하기]]></title>
            <link>https://velog.io/@dsts-01/%ED%85%8C%EB%8B%88%EC%8A%A4-%EB%B9%853%ED%8E%98%EB%8D%94%EB%9F%AC%EB%82%98%EB%8B%AC%EC%A1%B0%EC%BD%94%EB%B9%84%EC%B9%98%EC%9D%98-%EA%B7%B8%EB%9E%9C%EB%93%9C-%EC%8A%AC%EB%9E%A8-%EC%9A%B0%EC%8A%B9-%ED%9A%9F%EC%88%98-%ED%99%95%EC%9D%B8%ED%95%98%EA%B8%B0</link>
            <guid>https://velog.io/@dsts-01/%ED%85%8C%EB%8B%88%EC%8A%A4-%EB%B9%853%ED%8E%98%EB%8D%94%EB%9F%AC%EB%82%98%EB%8B%AC%EC%A1%B0%EC%BD%94%EB%B9%84%EC%B9%98%EC%9D%98-%EA%B7%B8%EB%9E%9C%EB%93%9C-%EC%8A%AC%EB%9E%A8-%EC%9A%B0%EC%8A%B9-%ED%9A%9F%EC%88%98-%ED%99%95%EC%9D%B8%ED%95%98%EA%B8%B0</guid>
            <pubDate>Thu, 22 Jul 2021 02:09:37 GMT</pubDate>
            <description><![CDATA[<h3 id="오늘-정리할-개념">오늘 정리할 개념</h3>
<p>데이터 사이언스를 공부하기 위한 기초 개념들 정리해본다.</p>
<ul>
<li>CSV</li>
<li>pandas</li>
<li>EDA</li>
<li>특성 공학(Feature Engineering)</li>
<li>데이터 조작(Data manipulation)</li>
<li>시각화란?</li>
</ul>
<h3 id="질문과--검색키워드-정리">질문과 =&gt; 검색키워드 정리</h3>
<ul>
<li>어떻게 하면 폴더 안에 파일을 한꺼번에 가져올 수 있을까? ⇒ os.listdir</li>
<li>어떻게 하면 csv 파일만 가져올 수 있을까? ⇒file.endswith</li>
<li>어떻게하면 하나의 데이터 프레임으로 만들 수 있을까? ⇒ concat, list comprehesion</li>
<li>인덱스 정리 ⇒ reset_index</li>
<li>소수점 자리수 정리 ⇒ round</li>
<li>데이터를 어떻게 합칠까? ⇒ concat</li>
<li>어떻게 시각화 할 수 있을까? ⇒matplotlib</li>
<li>어떻게하면 둥그런 형태로 차트를 그릴 수 있을까?⇒ pie chart</li>
<li>어떻게하면 각 연도별 횟수를 시각화할 수 있을까? ⇒ bar plot</li>
</ul>
<h1 id="페더러-경기-데이터를-가져오기">페더러 경기 데이터를 가져오기</h1>
<p>테니스 데이터를 바탕으로 내가 배워나간 개념들을 하나씩 정리해 나간다.</p>
<p>우선, 테니스 데이터를 가져온다. 테니스 데이터를 구하기 위해 여러가지 검색을 하였는데, 테니스 데이터를 오픈 소스로 제공하는 분의 githube를 찾았다(자원봉사 형태로 자료를 모으고, CSV 형태로 자료를 제공한다). 그 자료를 바탕으로 테니스 데이터를 분석하였다.</p>
<h2 id="판다스로-페더러-데뷔년도부터-데이터-가져오기">판다스로 페더러 데뷔년도부터 데이터 가져오기</h2>
<pre><code class="language-python"># 경로설정
path = &#39;./페더러데뷔년도&#39;
# 경로에 있는 모든 파일을 가져옴
file_list = os.listdir(path)
# 경로에 있는 csv 파일만 가져옴
file_list_py = [file for file in file_list if file.endswith(&#39;.csv&#39;)]</code></pre>
<p>위와 같이 csv파일만을 가져오는 list를 만든다.</p>
<pre><code class="language-python"># 데이터 프레임을 만들기
df_tennis = pd.DataFrame()

# file_list의 csv파일을 반복적으로 concat 시켜서 하나의 데이터 프레임으로 합친다.
for i in file_list:
    data = pd.read_csv(i) ## csv 파일을 불러온다.
    df_tennis = pd.concat([df_tennis, data]) ## 불러온 csv 파일을 하나로 합친다.</code></pre>
<h3 id="질문-⇒-검색키워드-velog에-구현방법-있음">&lt;질문 ⇒ 검색키워드, velog에 구현방법 있음&gt;</h3>
<ul>
<li>어떻게 하면 폴더 안에 파일을 한꺼번에 가져올 수 있을까? ⇒ os.listdir</li>
<li>어떻게 하면 csv 파일만 가져올 수 있을까? ⇒file.endswith</li>
<li>어떻게하면 하나의 데이터 프레임으로 만들 수 있을까? ⇒ concat, list comprehesion</li>
</ul>
<h2 id="페더러의-기본-정보-확인하기">페더러의 기본 정보 확인하기</h2>
<h3 id="edaexploratory-data-analysis란">EDA(Exploratory Data Analysis)란?</h3>
<p>탐색적 분석, “복잡한 모델링이나 수식을 쓰지 않고, 데이터를 탐색하는 것 “이다. 데이터를 탐색하는 것이 주 목적이다.</p>
<h3 id="atp-테니스-데이터">ATP 테니스 데이터</h3>
<p>오픈 소스 파일에 간단한 데이터 사전(data dictionary)를 제공하고 있었다.</p>
<pre><code># 필요한 특성들
##tourney_id : 투어 종류
##tourney_level : 그랜드슬램급 - G, 마스터즈급- M, 등등
##tourney_date : 경기 날짜
##winner_name : 이긴 선수 이름
##loser_name : 진 선수 이름 등</code></pre><p>내가 원하는 정보를 찾기 위해서 어떤 특성들을 알아야 하는지 살펴 보았다.</p>
<p>그 선수의 경기를 찾기 위해서는 상대방이 있는 단식게임이기 때문에, ‘winner_name’과 ‘loser-name’에 특정 선수 이름을 넣고 검색하면 그 선수의 경기 정보를 찾을 수 있다. 그리고 참가한 대회의 종류가 있어서, ‘tourney_level’ 특성에서 원하는 대회를 선택하여 정보를 찾을 수 있다.</p>
<pre><code># 1998년부터 2021년까지 가장 많은 승리를 가진 선수
df_tennis[&#39;winner_name&#39;].value_counts()
## 실행하면!
Roger Federer         1251
Rafael Nadal          1030
Novak Djokovic         962
David Ferrer           740
Andy Murray            686</code></pre><pre><code class="language-python"># 페더러 기록만 가져오기
## 페더러가 이긴 경기
df_federer_win = df_tennis[df_tennis[&#39;winner_name&#39;] == &#39;Roger Federer&#39;]
...

## 페더러가 진 경기
df_federer_lose = df_tennis[df_tennis[&#39;loser_name&#39;] == &#39;Roger Federer&#39;]
...
</code></pre>
<p>위와 같이, 데이터의 특성과 정보를 어떤 모델링을 쓰거나 수학적인 공식을 쓰지 않고 데이터 자체를 탐색하는 것을 EDA, 탐색적 분석이라고 부른다.</p>
<h3 id="페더러의-승리-패배-알아보기">페더러의 승리, 패배 알아보기</h3>
<h3 id="특성-공학feature-engineering이란">특성 공학(Feature Engineering)이란?</h3>
<p>“해당 분야에 대한 지식이나 창의성을 활용하여 데이터 셋 안에 항목들을 재조합, 새로운 데이터 만드는 것”이다. 예를 들어 전체의 경기 수, 테니스에서는 승리한 경기 수, 패배한 경기 수, ATP 경기 중 승률 등을 구하는 것이 해당한다.</p>
<h3 id="페더러의-기본-경기-정보">페더러의 기본 경기 정보</h3>
<p>페더러의 정보(전체 경기수/승리/패배/승률 등)를 확인해본다.</p>
<pre><code class="language-python">
#승리한 경기수
df_federer_win = df_tennis[df_tennis[&#39;winner_name&#39;] == &#39;Roger Federer&#39;]
df_federer_win= df_federer.reset_index(drop=True) ## index 정리
#진 경기수
df_federer_lose = df_tennis[df_tennis[&#39;loser_name&#39;] == &#39;Roger Federer&#39;]
df_federer_lose = df_federer_lose.reset_index(drop=True)## index 정리

#전체 경기수 
## 이긴 경기와 진 경기를 합쳐서 전체 경기수를 구한다.
df_federer_total = pd.concat([&#39;df_federer_lose, df_federer_win&#39;])

# 전체 경기수 / 승리수/ 패배 수/ 승률
total_num = len(df_federer_total)
win_num = len(df_federer_win) 
lose_num = len(df_federer_lose)
승률 :win_rate= win_num /total_num * 100
패배율 : lose_rate= lose_num /total_num * 100

## 전체경기/승리/패배
print(&#39;전체 경기 : &#39;,len(df_federer_total))
print(&#39;승리 :&#39;,len(df_federer_win))
print(&#39;패배 :&#39;,len(df_federer_lose))

## 소수자리수 정리
print(&#39;페더러 승률:&#39;, round(win_rate,2),&#39;%&#39;)
print(&#39;페더러 패배율:&#39;, round(lose_rate,2),&#39;%&#39;)
전체 경기 :  1528
승리 : 1251
패배 : 277
페더러 승률: 81.87 %
페더러 패배율: 18.13 %</code></pre>
<p>페더러의 기본 정보들을 가지고, 전체 경기수/승리/패배/승률 등을 만들어 낼 수 있다. 기존의 승리한 경기, 패배한 경기 데이터를 바탕으로 두 데이터를 조합하여 전체 경기의 데이터(df_federer_total)를 구하고, 그에 따라 승리수 or 패배수/전체 경기수를 구하여 승률과 패배율을 구하였다. 이와 같은 방식으로 기존의 데이터로 도메인지식이나 창의성을 활용하여 항목들을 재조합하여 새로운 데이터를 만들것을 &#39;특성공학&#39;, &#39;Feature Engineering&#39;이라고 한다.</p>
<h3 id="질문--키워드">&lt;질문 &amp; 키워드&gt;</h3>
<ul>
<li>인덱스 정리 ⇒ reset_index</li>
<li>소수점 자리수 정리 ⇒ round</li>
<li>데이터를 어떻게 합칠까? ⇒ concat</li>
</ul>
<h3 id="페더러는-atp-그랜드-슬램-대회에서-20회-우승한-것이-맞을까">페더러는 ATP 그랜드 슬램 대회에서 20회 우승한 것이 맞을까?</h3>
<h3 id="data-manipulation">Data manipulation?</h3>
<p>‘여러 개로 쪼개진 데이터를 하나의 데이터로 만들기도 하고 하나의 데이터셋에서 필요한 feature를 뽑아서 조합하는 것’을 의미한다.</p>
<p>여기서 전체 경기의 데이터를 만드는 과정에서 concat를 사용하여 데이터를 만들었는데, Data manipulation의 일종이라고 이야기 할 수 있다.</p>
<h3 id="그랜드-슬램-정보-가져오기">그랜드 슬램 정보 가져오기</h3>
<p>로저 페더러가 그랜드 슬램에 참여한 경기를 확인하고, 그곳에서 얼마나 우승하였는지 확인해 본다.</p>
<pre><code class="language-python"># 페더러 전 경기 중, 그랜드 슬램 경기 뽑아내기
df_federer_grandslam = df_federer_total[df_federer_total[&#39;tourney_level&#39;] == &#39;G&#39;] ## &#39;tourney_level&#39;에서 &#39;G&#39; 는 그랜드 슬램을 의미한다.

## 경기수
len(df_federer_grandslam) : 425

## 그랜드 슬램 라운드 확인
df_federer_grandslam[&#39;round&#39;].value_counts()

## 그랜드 슬램 결승전 진출 확인
df_federer_grandslam_final = df_federer_grandslam[df_federer_grandslam[&#39;round&#39;] == &#39;F&#39;] ## [&#39;round&#39;] == &#39;F&#39;] 결승진출을 이야기

## 그랜드 슬램 결승 진출 우승 확인
df_federer_grandslam_final_win = df_federer_grandslam_final[df_federer_grandslam_final[&#39;winner_name&#39;] == &#39;Roger Federer&#39; ] ## 결승 진출 후 우승하였는지 체크

### 각 그랜드 슬램별 횟수
print(&#39;그랜드 슬램 우승횟수:&#39;, len(df_federer_grandslam_final_win))
그랜드 슬램 우승횟수: 20

### 결승진출 시 승률 계산 &amp; 소수점 2번째 자리까지!
print(&quot;페더러 결승 진출시 우승확률:&quot;, round(len(df_federer_grandslam_final_win)/len(df_federer_grandslam_final),2),&#39;%&#39;)

페더러 결승 진출시 우승확률: 0.65 %

# 각 그랜드 슬램 우승 횟수
# 호주 오픈 우승횟수
print(&#39;호주 오픈 우승횟수 : &#39;,len(df_federer_australian_open_win))

# 프랑스 오픈 우승횟수

print(&#39;롤랑가로스 우승횟수 : &#39;,len(df_federer_roland_garros_win))

# 윔블던 우승횟수

print(&#39;윔블던 우승횟수 : &#39;,len(df_federer_wimbledon_win))

# U.S오픈 우승횟수
print(&#39;U.S오픈&#39; 우승횟수 : &#39;,len(df_federer_U.Sopen_win))

호주 오픈 우승횟수 :  6
롤랑가로스 우승횟수 :  1
윔블던 우승횟수 :  8
U.S오픈 우승횟수 :  5</code></pre>
<p>논리적으로 순차적으로 필요한 정보를 뽑아내 봤다.</p>
<ol>
<li>페더러의 전체 데이터 중에 그랜드 슬램에 경기 데이터를 뽑아낸다.</li>
<li>페더러가 그랜드 슬램 중 결승전에 진출한 경기를 뽑아낸다.</li>
<li>페더러가 결승전에서 이긴 경기를 뽑아낸다.</li>
<li>페더러의 그랜드 슬램 결승전 승률을 구하기 위해 결승전 이긴 수/결승전 진출 수를 구한다.</li>
<li>각 그랜드 슬램 별 우승 횟수를 확인한다.</li>
</ol>
<h3 id="어떻게-하면-각-연도별-그랜드-슬램-우승-횟수를-보여줄-수-있을까">어떻게 하면 각 연도별 그랜드 슬램 우승 횟수를 보여줄 수 있을까?</h3>
<p>그랜드 슬램 우승횟수를 확인하고, 더 궁금한 점이 있었다. 각 연도별 몇 번 우승했는지 궁금했다. 그래서 어떻게 자료를 만들어야 할지 고민했다.</p>
<h3 id="우선-각-연도별로-나누기로-했다">우선 각 연도별로 나누기로 했다.</h3>
<h3 id="날짜-데이터-다루기">날짜 데이터 다루기!</h3>
<pre><code>df_federer_grandslam_final_win[&#39;tourney_date&#39;] = pd.to_datetime(df_federer_grandslam_final_win[&#39;tourney_date&#39;], format=&#39;%Y%m%d&#39;)
## 년도별로 정리
df_federer_grandslam_final_win[&#39;tourney_date&#39;] = df_federer_grandslam_final_win[&#39;tourney_date&#39;].dt.year
df_federer_grandslam_final_win</code></pre><p>pandas에서 datetime을 다룰 수 있다. 그래서 년/월/일로 나누어서 이용할 수 있도록 바꾸고, 년도별로 구분하여 진행했다.</p>
<pre><code>## 각각의 연도 자동으로 횟수 정리/ 데이터 프레임으로 만들기
df_federer_grandslam_count = pd.DataFrame(df_federer_grandslam_final_win[&#39;tourney_date&#39;].value_counts())
df_federer_grandslam_count</code></pre><pre><code>     tourney_date
2004    3
2006    3
2007    3
2017    2
2005    2
2009    2
2018    1
2003    1
2008    1
2010    1
2012</code></pre><p>새롭게 데이터 프레임을 만들어서 각 연도별 횟수를 확인했다.</p>
<h3 id="잘-눈에-안들어오는-정보-어떻게-쉽게-보여줄까">잘 눈에 안들어오는 정보 어떻게 쉽게 보여줄까?</h3>
<p>함께 테니스를 치는 지인에게 이런 정보들을 찾을 수 있다고 이야기 했다. 그런데 눈에 안들어온다고 하였다. 한 눈에 들어올 방법이 없을까 고민했다.</p>
<h3 id="시각화란">시각화란?</h3>
<p>“데이터를 한 눈에 알아볼 수 있도록 변경하는 것” 의미한다.</p>
<h3 id="페더러의-구했던-정보-시각화파이차트">페더러의 구했던 정보 시각화(파이차트)</h3>
<pre><code>## 전체 게임 수 중에
fig = plt.figure(figsize=(5,5))</code></pre><pre><code>plt.title(&#39;No. Roger Federer wins and losses throughout his careers&#39;)
plt.pie([df_federer_win.count()[0], df_federer_lose.count()[0]], labels=[f&#39;{df_federer_win.count()[0]} matches win&#39;, f&#39;{df_federer_lose.count()[0]} matches lose&#39;], textprops={&#39;fontsize&#39;:20})</code></pre><p><img src="https://cdn-images-1.medium.com/max/720/1*dzWV6A4a02xCFolKTOzK6Q.png" alt="https://cdn-images-1.medium.com/max/720/1*dzWV6A4a02xCFolKTOzK6Q.png"></p>
<pre><code>## 승률
fig = plt.figure(figsize=(5,5))
plt.title(&#39;Rate. Roger Federer wins and losses throughout his careers&#39;)
plt.pie([win_rate, lose_rate], labels=[f&#39;{win_rate}% win_rate&#39;, f&#39;{lose_rate} % lose_rate&#39;], textprops={&#39;fontsize&#39;:20})</code></pre><p><img src="https://cdn-images-1.medium.com/max/720/1*6OFrsvKyyraWceog1T7TtA.png" alt="https://cdn-images-1.medium.com/max/720/1*6OFrsvKyyraWceog1T7TtA.png"></p>
<h3 id="페더러는-연도별로-몇-번-그랜드-슬램을-우승하였나">페더러는 연도별로 몇 번 그랜드 슬램을 우승하였나?</h3>
<pre><code>## 우승횟수 정리
plt.title(&#39;No. Grandslam Championships&#39;)
plt.yticks([1,2,3,4])</code></pre><pre><code>plt.bar(df_federer_grandslam_count.index, df_federer_grandslam_count[&#39;tourney_date&#39;])</code></pre><p><img src="https://cdn-images-1.medium.com/max/720/1*MlF_d4TkotENrlXmtrno7A.png" alt="https://cdn-images-1.medium.com/max/720/1*MlF_d4TkotENrlXmtrno7A.png"></p>
<h3 id="질문--키워드-1">&lt;질문 &amp; 키워드&gt;</h3>
<ul>
<li>어떻게 시각화 할 수 있을까? ⇒matplotlib</li>
<li>어떻게하면 둥그런 형태로 차트를 그릴 수 있을까?⇒ pie chart</li>
<li>어떻게하면 각 연도별 횟수를 시각화할 수 있을까? ⇒ bar plot</li>
</ul>
<h3 id="앞으로-더-살펴볼-수-있는-것들">앞으로 더 살펴볼 수 있는 것들</h3>
<ul>
<li>마스터즈 급 우승</li>
<li>투어급 우승</li>
<li>연속 주간 세계랭킹 1위 지속기간</li>
<li>각 선수별 통계자료 확인, 함수, 클래스화</li>
<li>이형택, 권순우 국내 선수들 기록 확인</li>
</ul>
<h3 id="데이터-사이언스로서-앞으로-진행해-나갈-것">데이터 사이언스로서 앞으로 진행해 나갈 것</h3>
<p>“로저 페더러는 정말 그랜드 슬램을 20회 우승했을까?”라는 질문으로 실제 테니스 데이터를 다뤄보았다. 이를 통해 데이터 분석에서 필요한 4가지 개념을 정리했다. EDA, Feature Engineering, Data Mainpulation, 시각화를 개념정리하고 실제 어떤 것들인지 살펴보았다. 9개월간 데이터 사이언스를 배운 시점에서 하루하루 배웠던 개념들을, 내가 가장 익숙하고 관심있는 데이터들을 활용하여 하나씩 정리해 나갈 것이다. 그 첫번째 시작이다.</p>
<h3 id="마치며">마치며.</h3>
<p>로저 페더러를 고트(GOAT, Greatest Of All Time : 역대 최고의 선수)라고 부르는지 그 이유의 첫번째 근거인 그랜드 슬램 20회 우승을 실제로 그런지 알아보았다. 방송국 혹은 위키피디아에서 제공하는 데이터를 확인하는 것이 아니라 실제 ‘날 것 데이터’(low data)에서 확인해보는 과정을 거쳤다. 이렇게 실제 내가 알고 있는 것들에 대해서 로우 레벨에 데이터에서 실제 시각화까지 하는 과정을 하나씩 정리해 나갈 것이다. 그 과정에서 내가 배우고 알고 있는 데이터 사이언스의 개념들을 차근차근 정리해 나갈 것이다.</p>
<h2 id="에러노트">에러노트</h2>
<h3 id="에러-발생">에러 발생</h3>
<pre><code class="language-python">df_federer_grandslam_final_win[&#39;tourney_date&#39;] = df_federer_grandslam_final_win[&#39;tourney_id&#39;].dt.year</code></pre>
<pre><code class="language-python">에러 메세지 : AttributeError: Can only use .dt accessor with datetimelike values</code></pre>
<p>에러가 발생했다. 그런데 처음에 이해가 되지 않았다. datatime 에러는 처음 보는 것이었다.</p>
<p>그래서 차근차근 문제를 접근해봤다.</p>
<ol>
<li>dtype으로 확인했다. 그런데 dtype이 object였다.</li>
<li>다른 데이터를 확인해보니 dtype이 datatime이었다.</li>
<li>코드에 문제가 있는 것으로 확인하여 다시 보았다.</li>
</ol>
<pre><code class="language-python">df_federer_grandslam_final_win[&#39;tourney_id&#39;].dt.year
=&gt; df_federer_grandslam_final_win[&#39;tourney_date&#39;].dt.year</code></pre>
<pre><code>## 착각하여 tourney_id로 잘못입력한 것</code></pre><p>코드를 확인하고 다시 진행해보니, 제대로 작동하였다.</p>
]]></description>
        </item>
        <item>
            <title><![CDATA[chart.js로 그랜드 슬램 우승 횟수 나타내기]]></title>
            <link>https://velog.io/@dsts-01/chart.js%EB%A1%9C-%EA%B7%B8%EB%9E%9C%EB%93%9C-%EC%8A%AC%EB%9E%A8-%EC%9A%B0%EC%8A%B9-%ED%9A%9F%EC%88%98-%EB%82%98%ED%83%80%EB%82%B4%EA%B8%B0</link>
            <guid>https://velog.io/@dsts-01/chart.js%EB%A1%9C-%EA%B7%B8%EB%9E%9C%EB%93%9C-%EC%8A%AC%EB%9E%A8-%EC%9A%B0%EC%8A%B9-%ED%9A%9F%EC%88%98-%EB%82%98%ED%83%80%EB%82%B4%EA%B8%B0</guid>
            <pubDate>Mon, 21 Jun 2021 06:16:33 GMT</pubDate>
            <description><![CDATA[<h1 id="데이터를-웹-상에서-차트로-그리는-방법을-생각해-본다">데이터를 웹 상에서 차트로 그리는 방법을 생각해 본다.</h1>
<h2 id="우선-chartjs와-부트스트랩을-가져온다">우선 chart.js와 부트스트랩을 가져온다.</h2>
<h3 id="구글에서-chartjs를-검색하고-부트스트랩을-검색하여-편리하게-화면을-구성할-수-있도록-활용한다">구글에서 &#39;chart.js&#39;를 검색하고, &#39;부트스트랩&#39;을 검색하여, 편리하게 화면을 구성할 수 있도록 활용한다.</h3>
<p><a href="https://cdnjs.com/libraries/Chart.js">https://cdnjs.com/libraries/Chart.js</a></p>
<p><a href="https://getbootstrap.kr/docs/5.0/getting-started/introduction/">https://getbootstrap.kr/docs/5.0/getting-started/introduction/</a></p>
<pre><code class="language-python"># chart.js를 불러올 수 있게 코드를 추가한다. 
## html 파일 head태그 부분에 코드를 추가한다.
&lt;script src=https://cdnjs.cloudflare.com/ajax/libs/Chart.js/3.3.2/chart.min.js&gt;&lt;/script&gt;

# 개발을 편하게 하기 위해서 부트스트랩 css코드를 추가한다.
## html 파일 head태그 부분에 코드를 추가한다.
&lt;link href=&quot;https://cdn.jsdelivr.net/npm/bootstrap@5.0.1/dist/css/bootstrap.min.css&quot; rel=&quot;stylesheet&quot; integrity=&quot;sha384-+0n0xVW2eSR5OomGNYDnhzAbDsOXxcvSN1TPprVMTNDbiYZCxYbOOl7+AMvyTG2x&quot; crossorigin=&quot;anonymous&quot;&gt;

### 예시
&lt;!DOCTYPE html&gt;
&lt;html lang=&quot;en&quot;&gt;
  &lt;head&gt;
    &lt;meta charset=&quot;UTF-8&quot; /&gt;
    &lt;title&gt;Document&lt;/title&gt;
    **&lt;script src=https://cdnjs.cloudflare.com/ajax/libs/Chart.js/3.3.2/chart.min.js&gt;&lt;/script&gt;
    &lt;link href=&quot;https://cdn.jsdelivr.net/npm/bootstrap@5.0.1/dist/css/bootstrap.min.css&quot; rel=&quot;stylesheet&quot;&gt;**
  &lt;/head&gt;
  &lt;body&gt;
  &lt;/body&gt;
&lt;/html&gt;</code></pre>
<h2 id="container를-활용하여-chartjs를-id를-설정해준다">container를 활용하여, chart.js를 id를 설정해준다.</h2>
<pre><code class="language-python"># body 태그에 div class로 화면 안에 들어갈 차트의 container 생성한다.
## canvas id로 내용을 담을 때 선택할 수 있도록 한다.
**&lt;div class=&quot;container&quot;&gt;
  &lt;div class=&quot;row&quot;&gt;
    &lt;div class=&quot;col-md-6&quot;&gt;
      &lt;canvas id=&quot;myChartOne&quot;&gt;&lt;/canvas&gt;
    &lt;/div&gt;
  &lt;/div&gt;
&lt;/div&gt;**

## 예시
&lt;!DOCTYPE html&gt;
&lt;html lang=&quot;en&quot;&gt;
  &lt;head&gt;
    &lt;meta charset=&quot;UTF-8&quot; /&gt;
    &lt;title&gt;Document&lt;/title&gt;
    **&lt;script src=https://cdnjs.cloudflare.com/ajax/libs/Chart.js/3.3.2/chart.min.js&gt;&lt;/script&gt;
    &lt;link href=&quot;https://cdn.jsdelivr.net/npm/bootstrap@5.0.1/dist/css/bootstrap.min.css&quot; rel=&quot;stylesheet&quot;&gt;**
  &lt;/head&gt;
  &lt;body&gt;
    **&lt;div class=&quot;container&quot;&gt;
      &lt;div class=&quot;row&quot;&gt;
        &lt;div class=&quot;col-md-6&quot;&gt;
          &lt;canvas id=&quot;myChartOne&quot;&gt;&lt;/canvas&gt;
        &lt;/div&gt;
      &lt;/div&gt;
    &lt;/div&gt;**
    &lt;h1&gt;hello world!!&lt;/h1&gt;
  &lt;/body&gt;
&lt;/html&gt;</code></pre>
<h2 id="script-태그로-변수를-설정하여-차트를-그려본다">script 태그로 변수를 설정하여, 차트를 그려본다.</h2>
<h3 id="페더러-그랜드-슬램-우승-횟수-chartjs로-나타내기">페더러 그랜드 슬램 우승 횟수 chart.js로 나타내기</h3>
<pre><code class="language-python">#화면을 구성하는 html 파일에 코드를 추가한다. 
## script 태그에 chart.js 코드를 추가한다. 

&lt;script&gt;
    let myChartOne = document.getElementById(&#39;myChartOne&#39;).getContext(&#39;2d&#39;);

    let barChart = new Chart(myChartOne, {
      type : &#39;bar&#39;, //pie, line, doughnut, polarArea
      data : {
        labels : [&#39;호주 오픈&#39;,&#39;롤랑 가로스&#39;, &#39;윔블던&#39;, &#39;U.S 오픈&#39;],
        datasets : [{
          label : &#39;페더러 그랜드 슬램 우승횟수&#39;,
          data : [
            5,
            1,
            8,
            5
          ]
        }]
      }
    });
  &lt;/script&gt;</code></pre>
<h2 id="다음과-같이-출력된다">다음과 같이 출력된다.</h2>
<p><img src="https://images.velog.io/images/dsts-01/post/317dbf24-329d-4d66-b323-ed832e8ed419/Screen%20Shot%202021-06-21%20at%206.47.49%20AM.png" alt=""></p>
<h2 id="그런데-차트가-뜨지-않는-현상이-생겼다">그런데 차트가 뜨지 않는 현상이 생겼다.</h2>
<p><img src="https://images.velog.io/images/dsts-01/post/fc6cd8ae-8176-4103-b380-2d76f8fbd5ee/Screen%20Shot%202021-06-21%20at%207.10.11%20AM.png" alt=""></p>
<h3 id="에러메세지">에러메세지</h3>
<pre><code class="language-python"># 에러메세지
Uncaught SyntaxError: Identifier &#39;tennisChartOne&#39; has already been declared

## 이유 변수를 똑같이 설정했다. 
**let tennisChartOne = document.getElementById(&#39;tennisChartOne&#39;).getContext(&#39;2d&#39;);
let tennisChartOne = new Chart(tennisChartOne, {**
      type: &#39;pie&#39;,
      data : {
        labels : [&#39;승률&#39;, &#39;패배율&#39;],
        datasets : [{
          labels : &#39;승패율&#39;
          data : [
          &#39;81,87%&#39;,
          &#39;18.13%&#39;
          ]
        }]
      }
    })</code></pre>
<p><img src="https://images.velog.io/images/dsts-01/post/25d7db67-f24e-4142-a992-ac37f189e656/Screen%20Shot%202021-06-21%20at%207.21.46%20AM.png" alt=""></p>
<pre><code class="language-python"># 에러 다시 한번발생
Uncaught SyntaxError: Unexpected identifier

## 문제는 콤마 하나를 안 찍었다. 

### 기존

let pieChartOne = new Chart(tennisChartOne, {
      type: &#39;pie&#39;,
      data : {
        labels : [&#39;승률&#39;, &#39;패배율&#39;],
        datasets : [{
          labels : &#39;승패율&#39;
          data : [
          &#39;81,87%&#39;,
          &#39;18.13%&#39;
          ]
        }]
      }
    });

### 변경후
let pieChartOne = new Chart(tennisChartOne, {
      type: &#39;pie&#39;,
      data : {
        labels : [&#39;승률&#39;, &#39;패배율&#39;],
        datasets : [{
          labels : &#39;승패율&#39;**,**
          data : [
          &#39;81,87%&#39;,
          &#39;18.13%&#39;
          ]
        }]
      }
    });</code></pre>
<h2 id="그런데도-파이차트-나오지-않음">그런데도 파이차트 나오지 않음.</h2>
<p><img src="https://images.velog.io/images/dsts-01/post/6dfd9a3c-2cef-48fb-908b-c1e686a5e156/Screen%20Shot%202021-06-21%20at%207.21.46%20AM.png" alt=""></p>
<h3 id="datasets에서-data에-들어가는-타입-변경-후-실행되었다">datasets에서 data에 들어가는 타입 변경 후 실행되었다.</h3>
<pre><code class="language-python"># 차트 데이터에는 숫자 타입이 들어가야 한다.

##변경전
let pieChartOne = new Chart(tennisChartOne, {
      type: &#39;pie&#39;,
      data : {
        labels : [&#39;승률&#39;, &#39;패배율&#39;],
        datasets : [{
          labels : &#39;승패율&#39;**,**
          data : [
          **&#39;81,87%&#39;,
          &#39;18.13%&#39;**
          ]
        }]
      }
    });

## 변경후
let pieChartOne = new Chart(tennisChartOne, {
      type: &#39;pie&#39;,
      data : {
        labels : [&#39;승률&#39;, &#39;패배율&#39;],
        datasets : [{
          labels : &#39;승패율&#39;**,**
          data : [
          **81,87,
          18.13**
          ]
        }]
      }
    });</code></pre>
<p><img src="https://images.velog.io/images/dsts-01/post/e17491e4-fa0a-404b-8d97-eb85f0b38191/Screen%20Shot%202021-06-21%20at%203.13.03%20PM.png" alt=""></p>
<p>이유는 data 안에 문자 타입이 아닌 숫자타입이 들어가야 실행되었다. </p>
<h2 id="앞으로-진행할-부분">앞으로 진행할 부분</h2>
<p>이제 chart.js로 어떻게 화면에 띄워야 할 지, 최소한 부분을 배웠다. 앞으로는 이 테니스 데이터의 csv 파일을 어떻게 DB에 저장하고, 그 DB에 저장된 데이터를 가져와서 웹 화면에 보여줄 지 추가적으로 공부하여야 한다. 그리고 쥬피터 노트북으로 분석했던 데이터를 어떻게 실제 웹사이트에서 연동되도록 하여야 할 지 방법을 찾아보면서 진행해야 한다.</p>
]]></description>
        </item>
        <item>
            <title><![CDATA[장고로 테니스 웹 어플리케이션 만들기 #2]]></title>
            <link>https://velog.io/@dsts-01/%EC%9E%A5%EA%B3%A0%EB%A1%9C-%ED%85%8C%EB%8B%88%EC%8A%A4-%EC%9B%B9-%EC%96%B4%ED%94%8C%EB%A6%AC%EC%BC%80%EC%9D%B4%EC%85%98-%EB%A7%8C%EB%93%A4%EA%B8%B0-2</link>
            <guid>https://velog.io/@dsts-01/%EC%9E%A5%EA%B3%A0%EB%A1%9C-%ED%85%8C%EB%8B%88%EC%8A%A4-%EC%9B%B9-%EC%96%B4%ED%94%8C%EB%A6%AC%EC%BC%80%EC%9D%B4%EC%85%98-%EB%A7%8C%EB%93%A4%EA%B8%B0-2</guid>
            <pubDate>Thu, 17 Jun 2021 15:41:25 GMT</pubDate>
            <description><![CDATA[<h1 id="장고로-개발해-나가기">장고로 개발해 나가기</h1>
<p>장고의 기본 구조를 이해해 나간다. </p>
<p>오늘은 post/redirect, 화면이 띄우기 위해서 여러 에러에 마주하다. </p>
<h2 id="requestpost를-입력하러-에러-발생">request.post를 입력하러 에러 발생</h2>
<pre><code class="language-python"># views.py

def index(request):
    print(request.post)

# 에러 메세지
에러 메세지 : AttributeError: &#39;WSGIRequest&#39; object has no attribute &#39;post&#39;
</code></pre>
<p>post라는 attribute는 없다는 에러 메세지가 발생했다. request는 대문자 POST라는 메서드만 존재</p>
<h2 id="redirect에러">redirect에러</h2>
<pre><code class="language-python">#test.py
def test(request):
    return redirect(&#39;/&#39;)

## 에러 메세지
NameError: name &#39;redirect&#39; is not defined

## 문제해결
from django.shortcuts import render, redirect</code></pre>
<p>import에 redirect를 추가 시켜주지 않아서 에러가 발생했었다. </p>
<h2 id="이미지-파일-추가하는-법">이미지 파일 추가하는 법</h2>
<pre><code class="language-python">#index.html 파일
## load static을 추가해준다.
{% load static %} ## 추가해준다.

  &lt;img src=&quot;{% static &#39;tennis_bg.jpg&#39; %}&quot; width=&quot;200px&quot; alt=&quot;&quot; /&gt;
  &lt;form action=&quot;/&quot; method=&quot;POST&quot;&gt;
    {% csrf_token %}
    &lt;input type=&quot;text&quot; name=&quot;id&quot; /&gt;&lt;br /&gt;
    &lt;input type=&quot;password&quot; name=&quot;pw&quot; /&gt;&lt;br /&gt;
    &lt;input type=&quot;submit&quot; value=&quot;로그인&quot; /&gt;
  &lt;/form&gt;</code></pre>
<h3 id="main어플에서-static-폴더를-만들고-그-안에-이미지-파일을-추가한다">main어플에서 static 폴더를 만들고 그 안에 이미지 파일을 추가한다.</h3>
<p><img src="https://images.velog.io/images/dsts-01/post/3a3a3849-0a22-4820-8e51-75eeb62df525/main%20static.png" alt=""></p>
<h3 id="setting에서-url을-설정해준다">setting에서 URL을 설정해준다.</h3>
<pre><code class="language-python"># setting.py에서

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

STATICFILES_DIRS = [
    BASE_DIR / &#39;static&#39;,
]</code></pre>
<p>STATICFILES_DIRS 변수를 만들어서 경로를 설정해준다.</p>
<h3 id="환경변수-설정">환경변수 설정</h3>
<pre><code class="language-python">##manage.py
import os
import sys

## 에러 메세지
NameError: name &#39;dotenv&#39; is not defined

## 해결
import dotenv 추가</code></pre>
<h2 id="환경변수를-설정해-준다">환경변수를 설정해 준다.</h2>
<p>해킹을 방지하기 위해서 장고에서 key를 제공하는데, 그 키를 github에 그냥 올릴 경우 보안상에 문제가 발생한다. 그것을 방지 하기 위해서 환경변수를 설정해준다. </p>
<pre><code class="language-python">## .env 
SECRET_KEY=&quot;my_key&quot; # 해서 쓰고

##setting.py
SECRET_KEY = os.environ.get[&#39;SECRET_KEY&#39;]

## 에러 발생
TypeError: &#39;method&#39; object is not subscriptable

## 문제해결
SECRET_KEY = os.environ[&#39;SECRET_KEY&#39;]</code></pre>
<h1 id="이용자에게-보여지는-templete확인">이용자에게 보여지는 templete확인</h1>
<pre><code class="language-python"># base.html
## 이미지파일을 하기 위해서 static 로드
**{% load static %}**
&lt;!DOCTYPE html&gt;
&lt;html lang=&quot;en&quot;&gt;
  &lt;head&gt;
    &lt;meta charset=&quot;UTF-8&quot; /&gt;
    &lt;title&gt;Document&lt;/title&gt;
  &lt;/head&gt;
  &lt;body&gt;
    &lt;h1&gt;hello world!!&lt;/h1&gt;
    {% block body%}  ## body블록 시작
    {% endblock body%} ## body블록 끝

    {% block footer%} ## footer 블록 시작
    {% endblock footer%} ## footer 블록 끝

    &lt;p&gt;footer&lt;/p&gt;
  &lt;/body&gt;
&lt;/html&gt;

# index.html
{% extends &#39;main/base.html&#39; %} ## base.html에 파일을 상속해 온다.
{% block body %} ## 바디 블록 시작

  &lt;img src=&quot;{% static &#39;tennis_bg.jpg&#39; %}&quot; width=&quot;200px&quot; alt=&quot;&quot; /&gt;
  &lt;form action=&quot;/&quot; method=&quot;POST&quot;&gt;
    # {% csrf_token %}
    &lt;input type=&quot;text&quot; name=&quot;id&quot; /&gt;&lt;br /&gt;
    &lt;input type=&quot;password&quot; name=&quot;pw&quot; /&gt;&lt;br /&gt;
    &lt;input type=&quot;submit&quot; value=&quot;로그인&quot; /&gt;
  &lt;/form&gt;

{% endblock body %} ## 바디 블록 끝</code></pre>
<h2 id="에러-발생">에러 발생</h2>
<h3 id="에러-메세지--load-static--위치가-잘못-되었을-때">에러 메세지 :{% load static %} 위치가 잘못 되었을 때</h3>
<p><img src="https://images.velog.io/images/dsts-01/post/f354ee19-1b24-4784-ad9e-e8ee4c1f4759/%E1%84%8B%E1%85%A6%E1%84%85%E1%85%A51.png" alt=""></p>
<pre><code class="language-python"># 문제해결
base.html에서 index.html로 
{% load static %} 옮김

# 위치 바꿈

# base.html
## 이미지파일을 하기 위해서 static 로드
&lt;!DOCTYPE html&gt;
&lt;html lang=&quot;en&quot;&gt;
  &lt;head&gt;
    &lt;meta charset=&quot;UTF-8&quot; /&gt;
    &lt;title&gt;Document&lt;/title&gt;
  &lt;/head&gt;
  &lt;body&gt;
    &lt;h1&gt;hello world!!&lt;/h1&gt;
    {% block body%}  ## body블록 시작
    {% endblock body%} ## body블록 끝

    {% block footer%} ## footer 블록 시작
    {% endblock footer%} ## footer 블록 끝

    &lt;p&gt;footer&lt;/p&gt;
  &lt;/body&gt;
&lt;/html&gt;

# index.html
**{% load static %}**
**{% extends &#39;main/base.html&#39; %} ## base.html에 파일을 상속해 온다.**
{% block body %} ## 바디 블록 시작

  &lt;img src=&quot;{% static &#39;tennis_bg.jpg&#39; %}&quot; width=&quot;200px&quot; alt=&quot;&quot; /&gt;
  &lt;form action=&quot;/&quot; method=&quot;POST&quot;&gt;
    # {% csrf_token %}
    &lt;input type=&quot;text&quot; name=&quot;id&quot; /&gt;&lt;br /&gt;
    &lt;input type=&quot;password&quot; name=&quot;pw&quot; /&gt;&lt;br /&gt;
    &lt;input type=&quot;submit&quot; value=&quot;로그인&quot; /&gt;
  &lt;/form&gt;

{% endblock body %} ## 바디 블록 끝</code></pre>
<h2 id="경로의-문제">경로의 문제</h2>
<h3 id="에러-메세지---extends-mainbasehtml-">에러 메세지 : {% extends &#39;main/base.html&#39; %}</h3>
<p><img src="https://images.velog.io/images/dsts-01/post/6a5fc4a7-5492-4233-8cc3-c8f401cee7c1/%E1%84%8B%E1%85%A6%E1%84%85%E1%85%A52.png" alt=""></p>
<pre><code class="language-python"># index.html
**{% load static %}**
**{% extends &#39;base.html&#39; %} ## main 제거**
{% block body %} ## 바디 블록 시작

  &lt;img src=&quot;{% static &#39;tennis_bg.jpg&#39; %}&quot; width=&quot;200px&quot; alt=&quot;&quot; /&gt;
  &lt;form action=&quot;/&quot; method=&quot;POST&quot;&gt;
    # {% csrf_token %}
    &lt;input type=&quot;text&quot; name=&quot;id&quot; /&gt;&lt;br /&gt;
    &lt;input type=&quot;password&quot; name=&quot;pw&quot; /&gt;&lt;br /&gt;
    &lt;input type=&quot;submit&quot; value=&quot;로그인&quot; /&gt;
  &lt;/form&gt;

{% endblock body %} ## 바디 블록 끝</code></pre>
<h2 id="순서의-문제">순서의 문제</h2>
<p><img src="https://images.velog.io/images/dsts-01/post/502879c9-8a1d-4675-bb84-33b0bb14eb5b/%E1%84%8B%E1%85%A6%E1%84%85%E1%85%A53.png" alt=""></p>
<pre><code class="language-python">
# index.html
**{% extends &#39;base.html&#39; %}** ## 가장 앞부분에 나오고
**{% load static %} ## 그 다음 load static이 나와야 한다.**
{% block body %} ## 바디 블록 시작

  &lt;img src=&quot;{% static &#39;tennis_bg.jpg&#39; %}&quot; width=&quot;200px&quot; alt=&quot;&quot; /&gt;
  &lt;form action=&quot;/&quot; method=&quot;POST&quot;&gt;
    # {% csrf_token %}
    &lt;input type=&quot;text&quot; name=&quot;id&quot; /&gt;&lt;br /&gt;
    &lt;input type=&quot;password&quot; name=&quot;pw&quot; /&gt;&lt;br /&gt;
    &lt;input type=&quot;submit&quot; value=&quot;로그인&quot; /&gt;
  &lt;/form&gt;

{% endblock body %} ## 바디 블록 끝</code></pre>
<h2 id="-파이썬-문법-오류">% 파이썬 문법 오류</h2>
<p><img src="https://images.velog.io/images/dsts-01/post/de92e2f2-e743-49a6-855c-9ddbae95c929/%E1%84%8B%E1%85%A6%E1%84%85%E1%85%A54.png" alt=""></p>
<pre><code class="language-python">**{% block body% }  =&gt; {% block body%} # 띄어쓰기 없이 해야 함.**
{% endblock body%}</code></pre>
<h2 id="마치며">마치며</h2>
<p>장고의 기본적인 화면을 띄우기 위해서 에러들과 함께 했다. 앞으로 계속 에러와 함께 할 것이다.</p>
]]></description>
        </item>
        <item>
            <title><![CDATA[장고로 테니스 웹 어플리케이션 만들기 #1]]></title>
            <link>https://velog.io/@dsts-01/%EC%9E%A5%EA%B3%A0%EB%A1%9C-%ED%85%8C%EB%8B%88%EC%8A%A4-%EC%9B%B9-%EC%96%B4%ED%94%8C%EB%A6%AC%EC%BC%80%EC%9D%B4%EC%85%98-%EB%A7%8C%EB%93%A4%EA%B8%B0-1</link>
            <guid>https://velog.io/@dsts-01/%EC%9E%A5%EA%B3%A0%EB%A1%9C-%ED%85%8C%EB%8B%88%EC%8A%A4-%EC%9B%B9-%EC%96%B4%ED%94%8C%EB%A6%AC%EC%BC%80%EC%9D%B4%EC%85%98-%EB%A7%8C%EB%93%A4%EA%B8%B0-1</guid>
            <pubDate>Thu, 17 Jun 2021 14:19:40 GMT</pubDate>
            <description><![CDATA[<h1 id="장고로-테니스-통계-데이터-시각화하고-재미있는-경기를-추천하는-모델">장고로 테니스 통계 데이터 시각화하고, 재미있는 경기를 추천하는 모델</h1>
<p>자신이 좋아하는 선수들의 테니스 통계 데이터를 차트화하여 볼 수 있는 페이지와 새롭게 열릴 경기에서 재미있을 만한 경기를 추천해주는 모델을 만들어 보려고 한다.  </p>
<h1 id="가상환경-세팅하기">가상환경 세팅하기</h1>
<p>우선 가상환경을 설정한다. 자신이 원하는 환경을 구축하기 위해 필요한 모듈을 모은 바구니라고 할 수 있다. 같은 모듈이라도 버전이 따라 다르고, 에러가 발생하고, 배포시 문제가 발생할 수 있기 때문에, 가상환경을 설정하여 개발하는 것이 효과적이다. </p>
<ul>
<li>key-word : conda environment</li>
<li><a href="https://conda.io/projects/conda/en/latest/user-guide/tasks/manage-environments.html">https://conda.io/projects/conda/en/latest/user-guide/tasks/manage-environments.html</a></li>
</ul>
<h2 id="콘다로-가상환경-세팅">콘다로 가상환경 세팅</h2>
<pre><code class="language-python">#콘다 버전확인
% conda --version

#콘다 가상환경 확인
% conda info --envs

#콘다로 새로운 가상환경 만들기 
% conda create --name &#39;new&#39;

#콘다로 새로운 가상환경, 파이썬 함께 설치
% conda create --name &#39;new&#39; pyhton=3.8

#콘다 가상환경 활성화하기
% conda activate new

#콘다 가상환경 비활성화
% conda deativate 

#콘다 가상환경 지우기
% conda env remove --name &#39;new&#39;</code></pre>
<p>콘다를 이용하여, 가상환경을 구축하고 지우는 내용을 정리했다. </p>
<h1 id="장고django-설치">장고(Django )설치</h1>
<p>장고는 파이썬의 풀스택 프레임워크이다. 사용자에게 보여지는 웹페이지부터 DB까지 한 번에 빠르게 개발할 수 있도록 고안된 프레임워크다. </p>
<h2 id="설치하기">설치하기</h2>
<pre><code class="language-python">#콘다 버전확인
% conda --version

#콘다 가상환경 확인
% conda info --envs

#콘다로 새로운 가상환경, 파이썬 함께 설치
% conda create --name tennisapp pyhton=3.8

#콘다 가상환경 활성화하기
% conda activate tennisapp

## 가상환경 실행 후 장고 설치
% pip install django

## 그 다음 장고 프로젝트 시작
% django-admin startproject tennisapp
</code></pre>
<p>가상환경을 세팅한 후, 가상환경에서 장고를 설치 한다. 이후 장고 프로젝트를 시작한다.</p>
<h3 id="django-서버-구동-안되었을-때">django 서버 구동 안되었을 때</h3>
<pre><code class="language-python">#터미널 입력 메세지
## 서버를 구동시키는 명령어
python manage.py runserver

## 에러메세지
  File &quot;manage.py&quot;, line 17
    ) from exc
         ^
SyntaxError: invalid syntax</code></pre>
<p>어떤 문제인지 잘 몰랐다가, stackoverflow를 확인해보니, python3 manage.py runserver를 입력하면 실행되었다. </p>
<p>문제해결 key-word : &quot;manage.py&quot; SyntaxError: invalid syntax</p>
<h3 id="sever-구동-안되는-경우">sever 구동 안되는 경우</h3>
<pre><code class="language-python">## main 못찾는 경우

File &quot;/Users/ohsekwang/codestates/수료후 테니스 프로젝트/django(테니스웹어플)/tennisapp/urls.py&quot;, line 7, in &lt;module&gt;
    path(&#39;&#39;, main),
NameError: name &#39;main&#39; is not defined
</code></pre>
<p>setting.py, urls.py, <a href="http://views.py">views.py</a>를 잘 체크하여 문제없이 실행해야 한다. </p>
<pre><code class="language-python">#urls.py에서
from main.views import index,test

#setting.py에서
INSTALLED_APPS = [
    &#39;main&#39;,&#39;test&#39;,
    &#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;,
]

## manage.py
if __name__ == &#39;__main__&#39;:
    main()
</code></pre>
<h2 id="개발한-내용-github에-commit-하기">개발한 내용 github에 commit 하기</h2>
<h3 id="로컬-환경에서-개발한-것-github에-올리기">로컬 환경에서 개발한 것 github에 올리기</h3>
<pre><code class="language-python">#개발이 진행중인 해당 폴더에 간다.
% cd tennisapp

# git을 연결해준다.
% git init

# git에 추가할 내용을 정한다.
## 모든 개발 내용을 추가한다.
git add .

# 개발한 내용이 무엇인지 적어준다.
% git commit -m &quot;tennis app start&quot;

# github에 새로 만든 레파지토리와 로컬과 연결한다.
git remote add origin git@github.com:sekwangoh/tennisapp.git

# github에 올린다.
git push origin master</code></pre>
<p>개발한 내용을 github에 올렸다. </p>
<p>기본적인 가상환경 세팅, 장고 설치, 장고 서버 구동, github 커밋까지 시도해봤다.</p>
]]></description>
        </item>
    </channel>
</rss>