
๊ธฐ๊ธฐ ์ถฉ์ ๊ณผ ์์ดํ์ด ์ฌ์ฉ์ด ๊ฐ๋ฅํ ์นดํ ๋ชฉ๋ก์ ์ ๋ฆฌํ๋ ์น์ฌ์ดํธ
๐ ์ ์ ์ฌํญ
- ํํ์ด์ง๋ css/styles.css ํ์ผ ์ฌ์ฉ
- /cafes ๊ฒฝ๋ก๋ cafes.html ํ์ผ์ ๋ ๋๋ง
- cafes.html ํ์ผ์ cafe-data.csv์ ๋ชจ๋ ๋ฐ์ดํฐ๋ฅผ ํ์ํ๋ ๋ถํธ์คํธ๋ฉ ํ๋ฅผ ํฌํจ
- ํํธ: cafes๋ผ๋ ๊ฐ์ฒด๋ /cafes ๊ฒฝ๋ก์์ cafes.html๋ก ์ ๋ฌ๋จ
- ์์น URL์ ํ ์์์ ์ ์ฒด ๋งํฌ ๋์ ์ต์ปค ํ๊ทธ๋ก ๋ ๋๋ง
('Maps Link'๋ผ๋ ๋งํฌ ํ ์คํธ๊ฐ ์์ด์ผ ํ๊ณ href๊ฐ ์ค์ ๋งํฌ)
- ํํธ: ๋ชจ๋ ์์น ๋งํฌ์ ์ฒ์ ๋ค ๊ธ์๋ 'http'๋ก ํ์
- ํํ์ด์ง์ 'Show Me!' ๋ฒํผ์ ํด๋ฆญํ๋ฉด cafes.html ํ์ด์ง๋ก ์ด๋
- ๋ฒํผ์ด ์๋ '/add' ๋น๋ฐ ๊ฒฝ๋ก๋ฅผ ์ถ๊ฐํ์ฌ URL์ ์ ๋ ฅํ ๊ฒฝ์ฐ add.html ํ์ผ๋ก ์ด๋
- ์ ๋ ฅํ ๋ฐ์ดํฐ๊ฐ ์ ํจํ URL์ธ์ง ํ์ธํ๋ ์ ํจ์ฑ ๊ฒ์ฆ ๊ท์น์ ์์น URL ํ๋์ ํฌํจ
- ์ฌ์ฉ์๊ฐ ์ฑ๊ณต์ ์ผ๋ก add.html์ ์์์ ์ ์ถํ ๊ฒฝ์ฐ ๋ฐ์ดํฐ๊ฐ cafe-data.csv์ ์ถ๊ฐ
- ํ๋ผ์คํฌ ๋ถํธ์คํฌ๋ฉ์ผ๋ก add.html ํ์ด์ง์ quick_form ๋ง๋ค๊ธฐ
๐ cafe-data.csv
Cafe Name,Location,Open,Close,Coffee,Wifi,Power
Lighthaus,https://goo.gl/maps/2EvhB4oq4gyUXKXx9,11AM, 3:30PM,โโโโ๏ธ,๐ช๐ช,๐๐๐
Esters,https://goo.gl/maps/13Tjc36HuPWLELaSA,8AM,3PM,โโโโ,๐ช๐ช๐ช,๐
โฆ
โจ๏ธ main.py
from flask import Flask, render_template, url_for
from flask_bootstrap import Bootstrap
from flask_wtf import FlaskForm
from werkzeug.utils import redirect
from wtforms import StringField, URLField, SelectField, TimeField, SubmitField
from wtforms.validators import DataRequired, URL
import csv
app = Flask(__name__)
app.config['SECRET_KEY'] = '8BYkEfBA6O6donzWlSihBXox7C0sKR6b'
Bootstrap(app)
class CafeForm(FlaskForm):
cafe = StringField('Cafe name', validators=[DataRequired()])
location = URLField('Cafe Location on Google Maps (URL)',
validators=[DataRequired(), URL(message='Invalid URL format')])
open = TimeField('Opening Time', validators=[DataRequired()])
close = TimeField('Closing Time', validators=[DataRequired()])
coffee_rating = SelectField('Coffee rating',
choices=[("โ", "โ"), ("โโ", "โโ"), ("โโโ", "โโโ"), ("โโโโ", "โโโโ"), ("โโโโโ", "โโโโโ")],
validators=[DataRequired()])
wifi_rating = SelectField('Wifi Strength Rating',
choices=[("โ", "โ"), ("๐ช", "๐ช"), ("๐ช๐ช", "๐ช๐ช"), ("๐ช๐ช๐ช", "๐ช๐ช๐ช"), ("๐ช๐ช๐ช๐ช", "๐ช๐ช๐ช๐ช"), ("๐ช๐ช๐ช๐ช๐ช", "๐ช๐ช๐ช๐ช๐ช")],
validators=[DataRequired()])
power_rating = SelectField('Power Socket Availability',
choices=[("โ", "โ"), ("๐", "๐"), ("๐๐", "๐๐"), ("๐๐๐", "๐๐๐"), ("๐๐๐๐", "๐๐๐๐"), ("๐๐๐๐๐", "๐๐๐๐๐")],
validators=[DataRequired()])
submit = SubmitField(label='Submit')
@app.route("/")
def home():
return render_template("index.html")
@app.route('/add', methods=["GET", "POST"])
def add_cafe():
form = CafeForm()
if form.validate_on_submit():
with open("cafe-data.csv", mode="a", encoding='utf-8') as csv_file:
csv_file.write(f"\n{form.cafe.data},"
f"{form.location.data},"
f"{form.open.data},"
f"{form.close.data},"
f"{form.coffee_rating.data},"
f"{form.wifi_rating.data},"
f"{form.power_rating.data}")
return redirect(url_for('cafes'))
return render_template('add.html', form=form)
@app.route('/cafes')
def cafes():
with open('cafe-data.csv', newline='', encoding='utf-8') as csv_file:
csv_data = csv.reader(csv_file, delimiter=',')
list_of_rows = []
for row in csv_data:
list_of_rows.append(row)
return render_template('cafes.html', cafes=list_of_rows)
if __name__ == '__main__':
app.run(debug=True)
๐๏ธ base.html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<meta
name="viewport"
content="width=device-width, initial-scale=1, shrink-to-fit=no"
/>
{% block styles %}
<!-- Load Bootstrap-Flask CSS here -->
<link href="https://cdn.jsdelivr.net/npm/bootstrap@5.1.3/dist/css/bootstrap.min.css" rel="stylesheet" integrity="sha384-1BmE4kWBq78iYhFldvKuhfTAU6auU8tT94WrHftjDbrCEXSU1oBoqyl2QvZ6jIW3" crossorigin="anonymous">
<!-- Link to the styles.css here to apply styling to all the child templates.-->
<link href="{{ url_for('static', filename='css/styles.css') }}" rel="stylesheet" />
{% endblock %}
<title>{% block title %}{% endblock %}</title>
</head>
<body>
{% block content %}{% endblock %}
</body>
</html>
๐๏ธ index.html
{% extends 'base.html' %}
{% block title %}Coffee and Wifi{% endblock %}
{% block content %}
<div class="jumbotron text-center">
<div class="container">
<h1 class="display-4">โ๏ธ Coffee & Wifi ๐ป</h1>
<p class="lead">Want to work in a cafe but need power and wifi?</p>
<hr class="my-4">
<p>You've found the right place! Checkout my collection of cafes with data on power socket availability, wifi speed and coffee quality.</p>
<a class="btn btn-warning btn-lg" href="{{ url_for('cafes') }}" role="button">Show Me!</a>
</div>
</div>
{% endblock %}
๐๏ธ cafes.html
{% extends 'base.html' %}
{% block title %}Restaurants{% endblock %}
{% block content %}
<div class="container">
<div class="row">
<div class="col-sm-12">
<h1>All Cafes</h1>
<table class="table table-dark table-striped table-hover">
<!-- cafe-data.csv ์ ์ ๋ณด๋ก ๋ถํธ์คํธ๋ฉ ํ ์ฑ์ฐ๊ธฐ-->
{% for row in cafes %}
<tr>
{% for item in row %}
{% if item[:4] == 'http' %}
<td><a href="{{ item }}">Maps Link</a></td>
{% else %}
<td>{{ item }}</td>
{% endif %}
{% endfor %}
</tr>
{% endfor %}
</table>
<p><a href="{{ url_for('home') }}">Return to index page</a></p>
</div>
</div>
</div>
{% endblock %}
๐๏ธ add.html
{% extends 'base.html' %}
{% import "bootstrap/wtf.html" as wtf %}
{% block title %}Add A New Cafe{% endblock %}
{% block content %}
<div class="container">
<div class="row">
<div class="col-sm-12 col-md-8">
<h1>Add a new cafe into the database</h1>
<!-- This is where your WTForm will go -->
{{ wtf.quick_form(form, novalidate=True) }}
<p class="space-above"><a href="{{ url_for('cafes') }}">See all cafes</a></p>
</div>
</div>
</div>
{% endblock %}