ใ‚ใกใ‚ƒใใกใ‚ƒ ้–‹็™บ่€…๐Ÿฆพ
์ฝ”๋”ฉ ์ง ๐Ÿ’ช
ใ‚ใกใ‚ƒใใกใ‚ƒ ้–‹็™บ่€…๐Ÿฆพ
  • ์นดํ…Œ๊ณ ๋ฆฌ (135)
    • ๊ฐœ๋ฐœ ํ™˜๊ฒฝ ๊ตฌ์ถ• (12)
      • ๊ฐœ๋ฐœ ํ™˜๊ฒฝ (5)
      • DB (0)
      • Node.js (4)
      • ํ˜•์ƒ ๊ด€๋ฆฌ (2)
      • Spring (1)
    • ์›น (11)
      • React (5)
      • ์ŠคํŒŒ๋ฅดํƒ€์ฝ”๋”ฉํด๋Ÿฝ__์›น (6)
    • ๋ชจ๋ฐ”์ผ (2)
      • ์•ˆ๋“œ๋กœ์ด๋“œ (2)
    • ํ”„๋กœ๊ทธ๋ž˜๋ฐ ์–ธ์–ด (55)
      • C (13)
      • Python (15)
      • SQL (5)
      • Java (22)
    • ์‚ฌ๋ฌผ์ธํ„ฐ๋„ท (11)
      • ์•„๋‘์ด๋…ธ (11)
    • ์ผ์ƒ (31)
      • ๋ง›์ง‘ (13)
      • ๋žญํ‚น๋‹ญ์ปด (4)
      • ํ›„๊ธฐ (11)
      • ์š”๋ฆฌ (3)
      • ์žก๋‹ด (0)
    • ๊ต์–‘ (4)
      • ์‹ฌ๋ฆฌํ•™ (3)
      • ํ…Œ๋‹ˆ์Šค (1)
    • ์ž๊ฒฉ์ฆ (9)
      • ์ •๋ณด์ฒ˜๋ฆฌ๊ธฐ์‚ฌ (9)

๋ธ”๋กœ๊ทธ ๋ฉ”๋‰ด

  • ๐Ÿ’ป github

์ธ๊ธฐ ๊ธ€

์ตœ๊ทผ ๊ธ€

ํ‹ฐ์Šคํ† ๋ฆฌ

hELLO ยท Designed By ์ •์ƒ์šฐ.
ใ‚ใกใ‚ƒใใกใ‚ƒ ้–‹็™บ่€…๐Ÿฆพ

์ฝ”๋”ฉ ์ง ๐Ÿ’ช

[์ŠคํŒŒ๋ฅดํƒ€์ฝ”๋”ฉํด๋Ÿฝ] ๐Ÿ’ป ์›น๊ฐœ๋ฐœ ์ข…ํ•ฉ - 4์ฃผ์ฐจ
์›น/์ŠคํŒŒ๋ฅดํƒ€์ฝ”๋”ฉํด๋Ÿฝ__์›น

[์ŠคํŒŒ๋ฅดํƒ€์ฝ”๋”ฉํด๋Ÿฝ] ๐Ÿ’ป ์›น๊ฐœ๋ฐœ ์ข…ํ•ฉ - 4์ฃผ์ฐจ

2022. 6. 22. 12:41

ใ€Š ์ŠคํŒŒ๋ฅดํƒ€์ฝ”๋”ฉํด๋Ÿฝ ์›น๊ฐœ๋ฐœ ์ข…ํ•ฉ โ€•1์ฃผ์ฐจโ€• ใ€‹

ใ€Š ์ŠคํŒŒ๋ฅดํƒ€์ฝ”๋”ฉํด๋Ÿฝ ์›น๊ฐœ๋ฐœ ์ข…ํ•ฉ โ€•2์ฃผ์ฐจโ€• ใ€‹

 ใ€Š ์ŠคํŒŒ๋ฅดํƒ€์ฝ”๋”ฉํด๋Ÿฝ ์›น๊ฐœ๋ฐœ ์ข…ํ•ฉ โ€•3์ฃผ์ฐจโ€• ใ€‹  


[ Flask ํ”„๋ ˆ์ž„์›Œํฌ ]

 - ๊ณต์‹ ํ™ˆํŽ˜์ด์ง€ : https://flask-docs-kr.readthedocs.io/ko/latest/index.html

 - ํŒŒ์ด์ฌ์œผ๋กœ ์ž‘์„ฑ๋œ ๋งˆ์ดํฌ๋กœ ์›น ํ”„๋ ˆ์ž„์›Œํฌ

 - Werkzeug ํˆดํ‚ท๊ณผ Jinja2 ํ…œํ”Œ๋ฆฟ ์—”์ง„์— ๊ธฐ๋ฐ˜์„ ๋‘” ํ”„๋ ˆ์ž„์›Œํฌ

 - ์›น ์—”์ง„๊ณผ ๋ถ™์—ฌ ์‚ฌ์šฉ ๊ฐ€๋Šฅํ•˜๋ฉฐ, API ์„œ๋ฒ„๋ฅผ ๋งŒ๋“ค๊ธฐ์— ํŽธ๋ฆฌํ•˜๋‹ค๋Š” ์žฅ์ ์ด ์žˆ์Œ

 

 

 

[ Flask Application ]

 - ์ฃผ๋กœ ์„œ๋ฒ„๋ฅผ ์‹คํ–‰ํ•  ๋ฉ”์ธ ํŒŒ์ผ์„ app.py๋กœ ์ง€์นญํ•˜์—ฌ ์‚ฌ์šฉ

 - ํŒŒ์ผ ์‹คํ–‰ ์‹œ http://localhost:5000/ ์œ„์น˜๋ฅผ ํ†ตํ•ด ์—ฐ๊ฒฐ ํ™•์ธ ๊ฐ€๋Šฅ

# ๊ธฐ๋ณธ ํ˜•์‹
from flask import Flask
app = Flask(__name__)

@app.route('/')
def hello_world():
    return 'Hello World!'

if __name__ == '__main__':
    app.run('0.0.0.0', port=5000, debug=True) # port๋ฒˆํ˜ธ๋ฅผ ํ†ตํ•ด ์ ‘์†

 

[ Flask Routing ]

 - ์›น ์• ํ”Œ๋ฆฌ์ผ€์ด์…˜์€ ๊ตฌ์กฐํ™”๋œ URL๋กœ ๊ตฌ์„ฑ๋˜์–ด ์žˆ์œผ๋ฉฐ,

   ์‚ฌ์šฉ์ž๊ฐ€ ์ธ๋ฑ์Šค ํŽ˜์ด์ง€๋ฅผ ๊ฑฐ์น˜์ง€ ์•Š๊ณ  ๋ฐ”๋กœ ์›ํ•˜๋Š” ํŽ˜์ด์ง€๋กœ ์ ‘๊ทผํ•  ์ˆ˜ ์žˆ์Œ

 - ์œ„์˜ route() ๋ฐ์ฝ”๋ ˆ์ดํ„ฐ๋Š” ํ•จ์ˆ˜์™€ URL์„ ์—ฐ๊ฒฐํ•ด์ฃผ๋Š” ์—ญํ• ์„ ํ•จ

# ๊ธฐ๋ณธ ํ˜•์‹
@app.route(‘/’)       # localhost:5000/ ํŽ˜์ด์ง€
def index():
  return ‘Index Page’
  
@app.route(‘/hello’)  # localhost:5000/hello ํŽ˜์ด์ง€
def hello():
  return ‘Hello World’

 

 

[ Flask ํ”„๋ ˆ์ž„์›Œํฌ ์‚ฌ์šฉ์‹œ ๊ธฐ๋ณธ ๊ตฌ์กฐ ์„ธํŒ… ]

 - ํ”„๋กœ์ ํŠธ ํด๋”  

    โ”” static ํด๋” (์ด๋ฏธ์ง€, css ํŒŒ์ผ ๊ด€๋ฆฌ)

    โ”” templates ํด๋” (html ํŒŒ์ผ ๊ด€๋ฆฌ)

    โ”” app.py (main ํŒŒ์ผ) 

 

 

[ render_template Method ]

 - ๊ธฐ๋ณธ ํ”„๋กœ์ ํŠธ ํด๋” ๋‚ด์— templates ํด๋”๋ฅผ ์ƒ์„ฑํ•˜์—ฌ html ํŒŒ์ผ์„ ๊ด€๋ฆฌํ•  ๊ฒฝ์šฐ

 - render_template() ๋ฉ”์†Œ๋“œ๋ฅผ ํ†ตํ•ด htmlํŒŒ์ผ์„ ๊ฐ„๋‹จํ•˜๊ฒŒ app.py์™€ render ๊ฐ€๋Šฅ

# ๊ธฐ๋ณธ ํ˜•์‹
from flask import render_template

@app.route('/')
def home():
  return render_template('index.html')

 - Flask๋Š” jinja ํ…œํ”Œ๋ฆฟ ์—”์ง„์„ ํ†ตํ•ด ์ž๋™์œผ๋กœ templates/html ํŒŒ์ผ์„ ์ด์Šค์ผ€์ดํ•‘

 

 

[ API ์ƒ์„ฑ ์˜ˆ์ œ ]

 - templates/ ํด๋”๋‚ด์— index.html ์ƒ์„ฑ 

 - ๋ฉ”์ธ ์•ฑ์ด ๋  app.py์™€ routing ๋ฐฉ์‹์„ ์‚ฌ์šฉํ•˜์—ฌ GET ์š”์ฒญ / POST ์š”์ฒญ ๋ฐฉ์‹์œผ๋กœ ์—ฐ๊ฒฐ ํ™•์ธ

<!-- index.html -->
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    
    <!-- aJax / jQuery CDN -->
    <script src="https://ajax.googleapis.com/ajax/libs/jquery/3.4.1/jquery.min.js"></script>
    <title>Document</title>
</head>
<body>
    <h1>์„œ๋ฒ„๋ฅผ ๋งŒ๋“ค์—ˆ๋‹ค!</h1>
</body>
</html>
ํ†ต์‹  ์š”์ฒญ ๋ฐฉ์‹ ์‚ฌ์šฉ ๋ฒ”์œ„ ๋ฐ์ดํ„ฐ ์ „๋‹ฌ ๋ฐฉ๋ฒ•
GET - ํ†ต์ƒ์ ์œผ๋กœ ๋ฐ์ดํ„ฐ ์กฐํšŒ ์š”์ฒญ
- ๋ฐ์ดํ„ฐ์˜ ๋ณ€๋™ ์—†์Œ
- Ex) ์˜ํ™” ๋ชฉ๋ก ์กฐํšŒ
- URL ๋’ค์— ๋ฌผ์Œํ‘œ๋ฅผ ๋ถ™์—ฌ key=value๋กœ ์ „๋‹ฌ
POST - ํ†ต์ƒ์ ์œผ๋กœ ๋ฐ์ดํ„ฐ ์ƒ์„ฑ, ๋ณ€๊ฒฝ, ์‚ญ์ œ ๋“ฑ ์š”์ฒญ
- Ex) ํšŒ์›๊ฐ€์ž…, ํšŒ์›ํƒˆํ‡ด, ๋น„๋ฐ€๋ฒˆํ˜ธ ๋ณ€๊ฒฝ
- ๋ณด์ด์ง€ ์•Š๋Š” HTML body์— key:value ํ˜•ํƒœ๋กœ ์ „๋‹ฌ
# app.py
from flask import Flask
app = Flask(__name__)

@app.route('/')
def home():
   return render_template('index.html')

# GET ์š”์ฒญ API
@app.route('/test', methods=['GET'])
def test_get():
   title_receive = request.args.get('title_give')
   print(title_receive)
   return jsonify({'result':'success', 'msg': '์ด ์š”์ฒญ์€ GET!'})

# POST ์š”์ฒญ API
@app.route('/test', methods=['POST'])
def test_post():
   title_receive = request.form['title_give']
   print(title_receive)
   return jsonify({'result':'success', 'msg': '์ด ์š”์ฒญ์€ POST!'})

if __name__ == '__main__':
   app.run('0.0.0.0', port=5000, debug=True)

 

 

 

(์ขŒ) ์ฝ˜์†”์„ ํ†ตํ•œ GET ์š”์ฒญ ์ •์ƒ ํ™•์ธ          (์šฐ) ์ฝ˜์†”์„ ํ†ตํ•œ POST ์š”์ฒญ ์ •์ƒ ํ™•์ธ 

ํ†ต์‹  ์š”์ฒญ ๋ฐฉ์‹ ajax ์š”์ฒญ ์ฝ”๋“œ 
GET - type : "GET"
- url : "/url?key=value"
- data : { }
POST - type : "POST"
- url : "/url"
- data : { key : value }

 

 

[ BS4 ๋ชจ๋“ˆ์„ ํ†ตํ•œ ๋ฉ”ํƒ€ํƒœ๊ทธ ํฌ๋กค๋ง ]

 - ๋ฉ”ํƒ€ํƒœ๊ทธ(MetaTag) :  ๊ฒ€์ƒ‰์—”์ง„ ์ตœ์ ํ™”(SEO)๋ฅผ ์œ„ํ•œ ์›นํŽ˜์ด์ง€์˜ ์š”์•ฝ ์ •๋ณด๋ฅผ ๋‹ด๊ณ  ์žˆ๋Š” ํƒœ๊ทธ

 - ๋ฐ˜๋“œ์‹œ <body/> ํƒœ๊ทธ ์•ž์— ์œ„์น˜ํ•ด์•ผ ํ•˜๋ฉฐ ๋ธŒ๋ผ์šฐ์ €์™€ ๊ฒ€์ƒ‰ ์—”์ง„์„ ํ†ตํ•ด ํ•ด๋‹น ์›นํŽ˜์ด์ง€์˜ ์ •๋ณด๋ฅผ ๋‚˜ํƒ€๋‚ผ ๋•Œ ์‚ฌ์šฉ

๋„ค์ด๋ฒ„ ์˜ํ™” ํŽ˜์ด์ง€์˜ ๋ฉ”ํƒ€ํƒœ๊ทธ

# meta ํƒœ๊ทธ ํฌ๋กค๋ง ์˜ˆ์ œ
import requests
from bs4 import BeautifulSoup

# -- requests settings --
url = 'https://movie.naver.com/movie/bi/mi/basic.nhn?code=171539' # ๋„ค์ด๋ฒ„ ์˜ํ™” '๊ทธ๋ฆฐ๋ถ' ํŽ˜์ด์ง€
headers = {'User-Agent' : 'Mozilla/5.0 (Windows NT 10.0; Win64; x64)AppleWebKit/537.36 (KHTML, like Gecko) Chrome/73.0.3683.86 Safari/537.36'}
data = requests.get(url,headers=headers)

# -- bs4 settings --
soup = BeautifulSoup(data.text, 'html.parser')

# -- meta tag crawling --
og_title = soup.select_one('meta[property="og:title"]')['content']
og_image = soup.select_one('meta[property="og:image"]')['content']
og_description = soup.select_one('meta[property="og:description"]')['content']

print(og_title) # ๋„ค์ด๋ฒ„ ์˜ํ™” ํŽ˜์ด์ง€์˜ ์ œ๋ชฉ ์ถœ๋ ฅ
print(og_image) # ๋„ค์ด๋ฒ„ ์˜ํ™” ํŽ˜์ด์ง€์˜ ์ด๋ฏธ์ง€ ๋งํฌ ์ถœ๋ ฅ
print(og_description) # ๋„ค์ด๋ฒ„ ์˜ํ™” ํŽ˜์ด์ง€์˜ ์„ค๋ช… ํ…์ŠคํŠธ ์ถœ๋ ฅ

์ถœ๋ ฅ ๊ฒฐ๊ณผ

 

ใ€Š ๋ชจ๋‘์˜ ์ฑ… ๋ฆฌ๋ทฐ ๋ฏธ๋‹ˆ ํ”„๋กœ์ ํŠธ ์˜ˆ์ œ ใ€‹

[ ํด๋”๊ตฌ์กฐ ]

 - bookReview

    โ”” static

    โ”” templates

         โ”” index.html

    โ”” app.py

 

[ ๋ฆฌ๋ทฐ ์ €์žฅ ]

 - (ํด๋ผ์ด์–ธํŠธ) ์ œ๋ชฉ, ์ €์ž, ๋ฆฌ๋ทฐ๋ฅผ ์‚ฌ์šฉ์ž๊ฐ€ ์ง์ ‘ ์ž…๋ ฅํ•˜์—ฌ POST ์š”์ฒญ ๋ฐฉ์‹์œผ๋กœ ์„œ๋ฒ„์— ๋ฐ์ดํ„ฐ๋ฅผ ์ „๋‹ฌ 

 - (์„œ๋ฒ„) ํด๋ผ์ด์–ธํŠธ๋กœ๋ถ€ํ„ฐ ์ „๋‹ฌ๋ฐ›์€ ๋ฐ์ดํ„ฐ๋ฅผ DB์— ์ €์žฅ

 

[ ๋ฆฌ๋ทฐ ๋„์‹ํ™” ]

 - (์„œ๋ฒ„) DB๋กœ๋ถ€ํ„ฐ ๋ชจ๋“  ๋ฐ์ดํ„ฐ๋ฅผ ๊ฐ€์ ธ์™€์„œ ํด๋ผ์ด์–ธํŠธ๋กœ ์ „๋‹ฌ

 - (ํด๋ผ์ด์–ธํŠธ) ์„œ๋ฒ„๋กœ๋ถ€ํ„ฐ GET ์š”์ฒญ ๋ฐฉ์‹์œผ๋กœ ์ „๋‹ฌ๋ฐ›์€ ๋ฐ์ดํ„ฐ๋ฅผ ๋ธŒ๋ผ์šฐ์ €์— ํ‘œํ˜„

 

 

 [ ํด๋ผ์ด์–ธํŠธ ํŒŒ์ผ (index.html) JavaScript ์ฝ”๋“œ ]

๋”๋ณด๊ธฐ

 - $(document).ready(function( ) ) { } : ๋ธŒ๋ผ์šฐ์ €๊ฐ€ ๋ถˆ๋ ค์˜ค๋Š” ์ฆ‰์‹œ ์‹คํ–‰ ๋˜๋Š” ํ•จ์ˆ˜(์ตœ์ดˆ ์‹คํ–‰ ํ•จ์ˆ˜)

  $(document).ready(function () {
    showReview();
  });

 

 - makeReview( ) : ๋ฆฌ๋ทฐ ๋ฐ•์Šค์˜ ๊ฐ ์š”์†Œ๋“ค์˜ ๊ฐ’์„ ๊ฐ€์ ธ์™€ POST์š”์ฒญ ๋ฐฉ์‹์œผ๋กœ ์„œ๋ฒ„๋กœ ์ „๋‹ฌํ•˜๋Š” ํ•จ์ˆ˜

  function makeReview() {
    let title = $("#title").val();
    let author = $("#author").val();
    let review = $("#bookReview").val();
    $.ajax({
      type: "POST",
      url: "/review",
      data: { title_give: title, author_give: author, review_give: review },
      success: function (response) {
        alert(response["msg"]);
        window.location.reload();
      },
    });
  }

 

 - showReview( ) : ์„œ๋ฒ„๋กœ๋ถ€ํ„ฐ GET ์š”์ฒญ๋ฐฉ์‹์„ ํ†ตํ•ด ๋ถˆ๋Ÿฌ์˜จ ๋ฐ์ดํ„ฐ๋“ค์„ HTML ์š”์†Œ์— ์‚ฝ์ž…ํ•˜๋Š” ํ•จ์ˆ˜

  function showReview() {
    $.ajax({
      type: "GET",
      url: "/review",
      data: {},
      success: function (response) {
        let reviews = response["all_reviews"];

        for (let i = 0; i < reviews.length; i++) {
          let title = reviews[i]["title"];
          let author = reviews[i]["author"];
          let review = reviews[i]["review"];

          let temp_html = `<tr>
                             <td>${title}</td>
                             <td>${author}</td>
                             <td>${review}</td>
                           </tr>`;
          $("#reviews-box").append(temp_html);
        }
      },
    });
  }

 

 

 

[ ์„œ๋ฒ„ ํŒŒ์ผ ( app.py ) ]

# app.py
from flask import Flask, render_template, jsonify, request
from pymongo import MongoClient

# -- Flask Server Run --
app = Flask(__name__)

# -- MongoDB Settings --
client = MongoClient('localhost', 27017)
db = client.dbsparta

# render_template ๋ฉ”์†Œ๋“œ๋ฅผ ํ†ตํ•ด HTML ์ „๋‹ฌ
@app.route('/')
def home():
    return render_template('index.html')

# -- API --
# ํด๋ผ์ด์–ธํŠธ๋กœ๋ถ€ํ„ฐ ๋ฆฌ๋ทฐ ๋ฐ์ดํ„ฐ ์ „๋‹ฌ๋ฐ›์•„ ๋”•์…”๋„ˆ๋ฆฌํ˜• ๋ฐ์ดํ„ฐ ์ƒ์„ฑ ํ›„ DB์— ์ƒ์„ฑ [ POST ์š”์ฒญ ]
@app.route('/review', methods=['POST'])
def write_review():
    title_receive = request.form['title_give']
    author_receive = request.form['author_give']
    review_receive = request.form['review_give']

    doc = { 'title':  title_receive,
            'author': author_receive,
            'review': review_receive }
    db.bookreview.insert_one(doc)

    return jsonify({'msg': '๋ฆฌ๋ทฐ ์ €์žฅ ์™„๋ฃŒ'})

# DB๋‚ด collection์˜ ๋ฐ์ดํ„ฐ๋ฅผ ๊ฐ€์ ธ์™€ ํด๋ผ์ด์–ธํŠธ๋กœ ์ „๋‹ฌ [ GET ์š”์ฒญ ]
@app.route('/review', methods=['GET'])
def read_reviews():
    reviews = list(db.bookreview.find({}, {'_id': False}))
    return jsonify({'all_reviews': reviews})


if __name__ == '__main__':
    app.run('0.0.0.0', port=5000, debug=True)

 

[ ์™„์„ฑ ๋ชจ์Šต ]

 

 

 

 

 

ใ€Š ๋‚˜ํ™€๋กœ ๋งํฌ ๋ฉ”๋ชจ์žฅ ํ”„๋กœ์ ํŠธ ์˜ˆ์ œ ใ€‹

[ ํด๋”๊ตฌ์กฐ ]

 - aloneMemo

    โ”” static

         โ”” index.css

    โ”” templates

         โ”” index.html

    โ”” app.py

 

[ ๊ธฐ์‚ฌ ์ €์žฅ ]

 - (ํด๋ผ์ด์–ธํŠธ) ํฌ์ŠคํŒ…๋ฐ•์Šค๋ฅผ ํ†ตํ•ด URL๊ณผ ์ฝ”๋ฉ˜ํŠธ๋ฅผ POST ์š”์ฒญ ๋ฐฉ์‹์œผ๋กœ ์„œ๋ฒ„์— ์ „๋‹ฌ

 - (์„œ๋ฒ„) ์ „๋‹ฌ๋ฐ›์€ URL์˜ ๋ฉ”ํƒ€ ํƒœ๊ทธ๋ฅผ ํฌ๋กค๋ง(์ œ๋ชฉ, ์ด๋ฏธ์ง€, ์„ค๋ช…, ๋งํฌ)ํ•˜์—ฌ DB์— ์ €์žฅ

 

[ ๊ธฐ์‚ฌ ๋„์‹ํ™” ]

 - (์„œ๋ฒ„) DB๋กœ๋ถ€ํ„ฐ ์ €์žฅ๋˜์–ด ์žˆ๋Š” ๋ฐ์ดํ„ฐ(์ œ๋ชฉ, ์ด๋ฏธ์ง€, ์„ค๋ช…, ๋งํฌ, ์ฝ”๋ฉ˜ํŠธ)๋ฅผ ํด๋ผ์ด์–ธํŠธ๋กœ ์ „๋‹ฌ

 - (ํด๋ผ์ด์–ธํŠธ) GET์š”์ฒญ ๋ฐฉ์‹์„ ํ†ตํ•ด ์„œ๋ฒ„๋กœ๋ถ€ํ„ฐ ์ „๋‹ฌ๋ฐ›์€ ๋ฐ์ดํ„ฐ๋ฅผ ๋ธŒ๋ผ์šฐ์ €์— ํ‘œํ˜„

 

[ ๊ธฐ์‚ฌ ์ œ๊ฑฐ ]

 - (ํด๋ผ์ด์–ธํŠธ) '์‚ญ์ œ' ๋ฒ„ํŠผ์„ ํ†ตํ•ด ํ•ด๋‹น ๊ธฐ์‚ฌ์˜ ์ •๋ณด๋ฅผ POST ์š”์ฒญ๋ฐฉ์‹์œผ๋กœ ์„œ๋ฒ„์— ์ „๋‹ฌ

 - (์„œ๋ฒ„) ํด๋ผ์ด์–ธํŠธ๋กœ๋ถ€ํ„ฐ ์ „๋‹ฌ๋ฐ›์€ ๋ฐ์ดํ„ฐ๋ฅผ DB์—์„œ ์‚ญ์ œ 

 

 

 [ ํด๋ผ์ด์–ธํŠธ ํŒŒ์ผ (index.html) JavaScript ์ฝ”๋“œ ]

๋”๋ณด๊ธฐ

 - $(document).ready(function( ) ) { } : ๋ธŒ๋ผ์šฐ์ €๊ฐ€ ๋ถˆ๋ ค์˜ค๋Š” ์ฆ‰์‹œ ์‹คํ–‰ ๋˜๋Š” ํ•จ์ˆ˜(์ตœ์ดˆ ์‹คํ–‰ ํ•จ์ˆ˜)

  $(document).ready(function(){
    showArticle();
  });

 

 - handleCommenting( ) : ๊ฐ„๋‹จ ์ฝ”๋ฉ˜ํŠธ์˜ ํ˜„์žฌ ๊ธ€์ž์ˆ˜๋ฅผ ํ‘œ์‹œํ•˜๊ณ  ์ด ๊ธ€์ž์ˆ˜๋ฅผ 24์ž๋กœ ์ œํ•œํ•˜๋Š” ํ•จ์ˆ˜

  function handleCommenting(response){
    $(".comment_count").html("(" + $(response).val().length + " / 24" + ")");
    if($(response).val().length > 24){
      $(response).val($(response).val().substring(0, 24));
      $(".comment_count").html("(24 / 24)");
    }
  }

 

 - handlePosting( ) : ์ดˆ๊ธฐ ํฌ์ŠคํŒ…๋ฐ•์Šค๋ฅผ '๋‹ซ๊ธฐ' ์ƒํƒœ๋กœ ์œ ์ง€ํ•˜๊ณ  ํด๋ฆญ์‹œ ๋งˆ๋‹ค ์ƒํƒœ๊ฐ€ ๋ณ€ํ•˜๋Š” ํ•จ์ˆ˜

  function handlePosting(){
    let status = $('.posting-box').css('display');
    if(status == 'block'){
      $('.posting-box').hide();
      $('#btn-posting-box').text('ํฌ์ŠคํŒ…๋ฐ•์Šค ์—ด๊ธฐ');
    }else{
      $('.posting-box').show();
      $('#btn-posting-box').text('ํฌ์ŠคํŒ…๋ฐ•์Šค ๋‹ซ๊ธฐ');
    }
  }

 

 - handleRemove( ) : ๊ธฐ์‚ฌ '์‚ญ์ œ' ๋ฒ„ํŠผ ํด๋ฆญ์‹œ ํ™•์ธ ์•ˆ๋‚ด ๋ฌธ๊ตฌ๋ฅผ ๋ณด์—ฌ์ฃผ๋Š” ํ•จ์ˆ˜

  function handleRemove(response){
    if(confirm("์ •๋ง ์‚ญ์ œํ•˜์‹œ๊ฒ ์Šต๋‹ˆ๊นŒ?")){
      deleteArticle($(response));
    } else{
      false;
    }
  };

 

 - deleteArticle( ) : ํ˜„์žฌ ๋ˆŒ๋Ÿฌ์ง„ '์‚ญ์ œ' ๋ฒ„ํŠผ ์š”์†Œ์˜ 'title'๊ณผ 'comment' ๊ฐ’์„ POST์š”์ฒญ ๋ฐฉ์‹์œผ๋กœ ์„œ๋ฒ„๋กœ ์ „๋‹ฌํ•˜๋Š” ํ•จ์ˆ˜

  function deleteArticle(response){
    let data = $(response)[0].dataset;
    let title = data.title;
    let comment = data.comment;
    $.ajax({
        type : 'post',
        url : '/delete',
        data : {article_title : title, article_comment : comment},
        success: function(response){
            alert(response["msg"]);
            window.location.reload()  // ํŽ˜์ด์ง€ ์ƒˆ๋กœ ๊ณ ์นจ
        }
    })
  }

 

 - postArticle( ) : ํ˜„์žฌ ํฌ์ŠคํŒ…๋ฐ•์Šค์˜ url ๊ฐ’๊ณผ comment ๊ฐ’์„ POST์š”์ฒญ ๋ฐฉ์‹์œผ๋กœ ์„œ๋ฒ„๋กœ ์ „๋‹ฌํ•˜๋Š” ํ•จ์ˆ˜

  function postArticle(){
    let url = $(".post-url").val();
    let comment = $(".post-comment").val();
    $.ajax({
        type : 'post',
        url : '/memo',
        data : {url_give : url, comment_give : comment},
        success: function(response){
            alert(response["msg"]);
            window.location.reload()  // ํŽ˜์ด์ง€ ์ƒˆ๋กœ ๊ณ ์นจ
        }
    })
  }

 - showArticle ( ) : ์„œ๋ฒ„๋กœ๋ถ€ํ„ฐ GET์š”์ฒญ ๋ฐฉ์‹์„ ํ†ตํ•ด title, image, comment ๋“ฑ์˜ ์ •๋ณด๋ฅผ ์ „๋‹ฌ๋ฐ›์•„ html ์š”์†Œ์— ์‚ฝ์ž…ํ•˜๋Š” ํ•จ์ˆ˜

  function showArticle(){
    $.ajax({
      type: "GET",
      url: "/memo",
      data: {},
      success: function(response){
        let articles = response['all_articles'];
        for(let i=0; i<articles.length; i++){
          let title = articles[i]["title"];
          let image = articles[i]["image"];
          let comment = articles[i]["comment"];
          let url = articles[i]["url"];
          let description = articles[i]["description"];

          let temp_html = `<div class="card">
                            <img
                              class="card-img-top"
                              src="${image}"
                              alt="Card image cap"
                            />
                            <div class="card-body">
                              <a href="${url}" class="card-title">${title}</a>
                              <p class="card-text">${description.slice(0, 180)}</p>
                              <p class="card-comment">${comment.slice(0, 24)}</p>
                            </div>
                            <button type="button"
                                    class="article-btn btn btn-danger" 
                                    data-title="${title}"
                                    data-comment="${comment}"
                                    onclick="handleRemove(this)">์‚ญ์ œ</button>
                          </div>`;

          $(".card-columns").append(temp_html);
        }
      }
    })
  }

 

 

 

[ ์„œ๋ฒ„ ํŒŒ์ผ ( app.py ) ]

from flask import Flask, render_template, jsonify, request
import requests
from bs4 import BeautifulSoup
from pymongo import MongoClient

# -- flask settings --
app = Flask(__name__)

# -- pyMongo settings --
client = MongoClient('localhost', 27017)
db = client.dbsparta

## -- flask APP Routing --
@app.route('/')
def home():
   return render_template('index.html')

# Listing API
@app.route('/memo', methods=['GET'])
def listing():
    articles = list(db.articles.find({}, {'_id': False}))
    return jsonify({'all_articles': articles})

# Posting API
@app.route('/memo', methods=['POST'])
def saving():
    url_receive = request.form['url_give']
    comment_receive = request.form['comment_give']

    # request
    headers = {
        'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64)AppleWebKit/537.36 (KHTML, like Gecko) Chrome/73.0.3683.86 Safari/537.36'}
    data = requests.get(url_receive, headers=headers)

    # bs4 set
    soup = BeautifulSoup(data.text, 'html.parser')
    og_title = soup.select_one('meta[property="og:title"]')['content']
    og_image = soup.select_one('meta[property="og:image"]')['content']
    og_description = soup.select_one('meta[property="og:description"]')['content']

    # pyMongo set
    doc = {'title': og_title,
           'image': og_image,
           'description': og_description,
           'url': url_receive,
           'comment': comment_receive}

    db.articles.insert_one(doc)

    return jsonify({'msg': '๊ธฐ์‚ฌ ์ €์žฅ์ด ์™„๋ฃŒ๋˜์—ˆ์Šต๋‹ˆ๋‹ค.'})

# Delete API
@app.route('/delete', methods=['POST'])
def delete_article():
    title = request.form['article_title']
    comment = request.form['article_comment']

    # pyMongo set
    collection = db.articles
    target_data = collection.find_one({'title': title, 'comment': comment}, {'_id': False})
    collection.delete_one(target_data)

    return jsonify({'msg': '๊ธฐ์‚ฌ๊ฐ€ ์ œ๊ฑฐ๋˜์—ˆ์Šต๋‹ˆ๋‹ค.'})

if __name__ == '__main__':
   app.run('0.0.0.0', port=5000, debug=True)

 

 

 

[ ์™„์„ฑ ๋ชจ์Šต ]

 

 

 

ใ€Š ๋‚˜ํ™€๋กœ ์‡ผํ•‘๋ชฐ ํ”„๋กœ์ ํŠธ ์˜ˆ์ œ ใ€‹

[ ํด๋”๊ตฌ์กฐ ]

 - aloneShop

    โ”” static

         โ”” index.css

         โ”” eva_t.jpg

    โ”” templates

         โ”” index.html

    โ”” app.py

 

[ ์ฃผ๋ฌธ ์ •๋ณด ์ €์žฅ ]

 - (ํด๋ผ์ด์–ธํŠธ) ์ฃผ๋ฌธ ์ •๋ณด ์ž…๋ ฅ์„ ํ†ตํ•ด ์ด๋ฆ„, ์ˆ˜๋Ÿ‰, ์ฃผ์†Œ, ์ „ํ™”๋ฒˆํ˜ธ๋ฅผ POST ์š”์ฒญ ๋ฐฉ์‹์œผ๋กœ ์„œ๋ฒ„์— ์ „๋‹ฌ

 - (์„œ๋ฒ„) ์ „๋‹ฌ๋ฐ›์€ ๋ฐ์ดํ„ฐ๋“ค์˜ ์ •๋ณด๋ฅผ DB์— ์ €์žฅ

 

[ ์ฃผ๋ฌธ ๋‚ด์—ญ ํ‘œ์‹œ ]

 - (์„œ๋ฒ„) DB๋กœ๋ถ€ํ„ฐ ์ €์žฅ๋˜์–ด ์žˆ๋Š” ๋ฐ์ดํ„ฐ๋ฅผ ํด๋ผ์ด์–ธํŠธ๋กœ ์ „๋‹ฌ

 - (ํด๋ผ์ด์–ธํŠธ) GET์š”์ฒญ ๋ฐฉ์‹์„ ํ†ตํ•ด ์„œ๋ฒ„๋กœ๋ถ€ํ„ฐ ์ „๋‹ฌ๋ฐ›์€ ๋ฐ์ดํ„ฐ๋ฅผ ๋ธŒ๋ผ์šฐ์ €์— ํ‘œ์‹œ

 

[ ์ฃผ๋ฌธ ๋‚ด์—ญ ์ œ๊ฑฐ ]

 - (ํด๋ผ์ด์–ธํŠธ) 'X' ๋ฒ„ํŠผ์„ ํ†ตํ•ด ํ•ด๋‹น ์ฃผ๋ฌธ๋‚ด์—ญ์˜ ์ •๋ณด๋ฅผ POST ์š”์ฒญ๋ฐฉ์‹์œผ๋กœ ์„œ๋ฒ„์— ์ „๋‹ฌ

 - (์„œ๋ฒ„) ํด๋ผ์ด์–ธํŠธ๋กœ๋ถ€ํ„ฐ ์ „๋‹ฌ๋ฐ›์€ ๋ฐ์ดํ„ฐ๋ฅผ DB์—์„œ ์‚ญ์ œ 

 

 

 [ ํด๋ผ์ด์–ธํŠธ ํŒŒ์ผ (index.html) JavaScript ์ฝ”๋“œ ]

๋”๋ณด๊ธฐ

 - $(function( ) ) { } : ๋ธŒ๋ผ์šฐ์ €๊ฐ€ ๋ถˆ๋ ค์˜ค๋Š” ์ฆ‰์‹œ ์‹คํ–‰ ๋˜๋Š” ํ•จ์ˆ˜(์ตœ์ดˆ ์‹คํ–‰ ํ•จ์ˆ˜)

  $(function () {
    $(".exchange_rate__btn").empty(); // ํ™˜์œจ ํ‘œ์‹œ๋ž€ ๋น„์šฐ๊ธฐ
    $.ajax({                          // GET์š”์ฒญ ๋ฐฉ์‹์œผ๋กœ ์ƒˆ๋กœ๊ณ ์นจ์‹œ ๋งˆ๋‹ค ์ƒˆ๋กœ์šด ํ™˜์œจ ์ ์šฉ
      type: "GET",
      url: "http://spartacodingclub.shop/sparta_api/rate",
      data: {},
      success: function (response) {
        let rate = response["rate"];

        $(".exchange_rate").append(`<span>: ${rate}</span>`);
      },
    });

    showOrders()                      // ์ฃผ๋ฌธ๋‚ด์—ญ ํ‘œ์‹œ
  });

 

 - showOrders( ) : GET์š”์ฒญ ๋ฐฉ์‹์„ ํ†ตํ•ด ์„œ๋ฒ„๋กœ๋ถ€ํ„ฐ ๋ฐ›์€ ๋ฐ์ดํ„ฐ๋ฅผ HTML ์š”์†Œ์— ์‚ฝ์ž…ํ•˜๋Š” ํ•จ์ˆ˜

  function showOrders(){
    $.ajax({
      type: "GET",
      url: "/orderInfo",
      data: {},
      success: function(response){
        let orders = response['all_orders'];
        for(let i=0; i<orders.length; i++){
          let order_name = orders[i]["order_name"];
          let order_amount = orders[i]["order_amount"];
          let order_address = orders[i]["order_address"];
          let order_phone = orders[i]["order_phone"];

          let temp_html = `<tr>
                            <td>${order_name}</td>
                            <td>${order_amount}</td>
                            <td>${order_address}</td>
                            <td>${order_phone}
                              <button type="button"
                                      class="delete-btn btn btn-danger"
                                      data-name="${order_name}"
                                      data-amount="${order_amount}"
                                      onclick="handleRemove(this)">X</button>
                            </td>
                          </tr>`;

          $(".orders_table").append(temp_html);
        }
      }
    })
  }

 

 - addOrders( ) : ์ž…๋ ฅํ•œ ์ฃผ๋ฌธ์ •๋ณด ๊ฐ’์„ ๊ฐ€์ ธ์™€ POST์š”์ฒญ ๋ฐฉ์‹์œผ๋กœ ์„œ๋ฒ„๋กœ ์ „๋‹ฌํ•˜๋Š” ํ•จ์ˆ˜

  function addOrders(){
    let name = $(".order-name").val();
    let amount = $(".order-amount").val();
    let adreess = $(".order-address").val();
    let phone = $(".order-phone").val();
    $.ajax({
        type : 'post',
        url : '/orderInfo',
        data : {name_give: name, amount_give: amount,
               address_give: adreess, phone_give: phone },
        success: function(response){
            alert(response["msg"]);
            window.location.reload()  // ํŽ˜์ด์ง€ ์ƒˆ๋กœ ๊ณ ์นจ
        }
    })
  }

 

 - deleteOrder( ) : 'X' ๋ฒ„ํŠผ ํด๋ฆญ์„ ํ†ตํ•ด ํ•ด๋‹น ์ฃผ๋ฌธ๋‚ด์—ญ์˜ ์ •๋ณด๋ฅผ POST ์š”์ฒญ๋ฐฉ์‹์œผ๋กœ ์„œ๋ฒ„๋กœ ์ „๋‹ฌํ•˜๋Š” ํ•จ์ˆ˜

  function deleteOrder(response){
    let data = $(response)[0].dataset;
    let name = data.name;
    let amount = data.amount;
    $.ajax({
        type : 'post',
        url : '/delete',
        data : {order_name : name, order_amount : amount},
        success: function(response){
            alert(response["msg"]);
            window.location.reload()  // ํŽ˜์ด์ง€ ์ƒˆ๋กœ ๊ณ ์นจ
        }
    })
  }

 

 

 

[ ์„œ๋ฒ„ ํŒŒ์ผ ( app.py ) ]

from flask import Flask, render_template, jsonify, request
from pymongo import MongoClient

# -- flask settings --
app = Flask(__name__)

# -- pyMongo settings --
client = MongoClient('localhost', 27017)
db = client.dbsparta

## -- flask APP Routing --
@app.route('/')
def home():
   return render_template('index.html')

# Listing API
@app.route('/orderInfo', methods=['GET'])
def listing():
    orders = list(db.orders.find({}, {'_id': False}))
    return jsonify({'all_orders': orders})

# Ordering API
@app.route('/orderInfo', methods=['POST'])
def saving():
    name_receive = request.form['name_give']
    amount_receive = request.form['amount_give']
    address_receive = request.form['address_give']
    phone_receive = request.form['phone_give']

    # pyMongo set
    doc = {'order_name': name_receive,
           'order_amount': amount_receive,
           'order_address': address_receive,
           'order_phone': phone_receive}

    db.orders.insert_one(doc)

    return jsonify({'msg': '์ฃผ๋ฌธ์ด ์™„๋ฃŒ๋˜์—ˆ์Šต๋‹ˆ๋‹ค.'})

# Delete API
@app.route('/delete', methods=['POST'])
def delete_article():
    name = request.form['order_name']
    amount = request.form['order_amount']

    # pyMongo set
    collection = db.orders
    target_data = collection.find_one({'order_name': name, 'order_amount': amount}, {'_id': False})
    collection.delete_one(target_data)

    return jsonify({'msg': '์ฃผ๋ฌธ ์ •๋ณด๊ฐ€ ์ œ๊ฑฐ๋˜์—ˆ์Šต๋‹ˆ๋‹ค.'})

if __name__ == '__main__':
   app.run('0.0.0.0', port=5000, debug=True)

 

[ ์™„์„ฑ ๋ชจ์Šต ]

์ €์ž‘์žํ‘œ์‹œ ๋น„์˜๋ฆฌ ๋ณ€๊ฒฝ๊ธˆ์ง€
    '์›น/์ŠคํŒŒ๋ฅดํƒ€์ฝ”๋”ฉํด๋Ÿฝ__์›น' ์นดํ…Œ๊ณ ๋ฆฌ์˜ ๋‹ค๋ฅธ ๊ธ€
    • [์ŠคํŒŒ๋ฅดํƒ€์ฝ”๋”ฉํด๋Ÿฝ] ๐Ÿ’ป ์›น๊ฐœ๋ฐœ ์ข…ํ•ฉ - 5์ฃผ์ฐจ (2) (ๅฎŒ)
    • [์ŠคํŒŒ๋ฅดํƒ€์ฝ”๋”ฉํด๋Ÿฝ] ๐Ÿ’ป ์›น๊ฐœ๋ฐœ ์ข…ํ•ฉ - 5์ฃผ์ฐจ (1)
    • [์ŠคํŒŒ๋ฅดํƒ€์ฝ”๋”ฉํด๋Ÿฝ] ๐Ÿ’ป ์›น๊ฐœ๋ฐœ ์ข…ํ•ฉ - 3์ฃผ์ฐจ
    • [์ŠคํŒŒ๋ฅดํƒ€์ฝ”๋”ฉํด๋Ÿฝ] ๐Ÿ’ป ์›น๊ฐœ๋ฐœ ์ข…ํ•ฉ - 2์ฃผ์ฐจ
    ใ‚ใกใ‚ƒใใกใ‚ƒ ้–‹็™บ่€…๐Ÿฆพ
    ใ‚ใกใ‚ƒใใกใ‚ƒ ้–‹็™บ่€…๐Ÿฆพ
    ๐Ÿ‘Š ๋ธ”๋กœ๊ทธ๋„ ๊ทผ์„ฑ์ด๋‹ค? ๐Ÿ‘Š

    ํ‹ฐ์Šคํ† ๋ฆฌํˆด๋ฐ”