Day 064

Udemy Python Bootcamp Day 064

My Top 10 Movies Website

View Movie List Items

from flask import Flask, render_template, redirect, url_for, request
from flask_bootstrap import Bootstrap
from flask_sqlalchemy import SQLAlchemy
from flask_wtf import FlaskForm
from wtforms import StringField, SubmitField
from wtforms.validators import DataRequired
import requests

app = Flask(__name__)
app.config['SECRET_KEY'] = '8BYkEfBA6O6donzWlSihBXox7C0sKR6b'
Bootstrap(app)

app.config['SQLALCHEMY_DATABASE_URI'] = "sqlite:///movie.db"
app.config['SQLALCHEMY_TRACK_MODIFICATIONS'] = False
db = SQLAlchemy(app)


class Movie(db.Model):
    id = db.Column(db.Integer, primary_key=True)
    title = db.Column(db.String(250), unique=True, nullable=False)
    year = db.Column(db.Integer, nullable=False)
    description = db.Column(db.String(500), nullable=False)
    rating = db.Column(db.Float, nullable=True)
    ranking = db.Column(db.Integer, nullable=True)
    review = db.Column(db.String(250), nullable=True)
    img_url = db.Column(db.String(250), nullable=False)
db.create_all()


@app.route("/")
def home():
    # new_movie = Movie(
    #     title="Phone Booth",
    #     year=2002,
    #     description="Publicist Stuart Shepard finds himself trapped in a phone booth, pinned down by an extortionist's sniper rifle. Unable to leave or receive outside help, Stuart's negotiation with the caller leads to a jaw-dropping climax.",
    #     rating=7.3,
    #     ranking=10,
    #     review="My favourite character was the caller.",
    #     img_url="https://image.tmdb.org/t/p/w500/tjrX2oWRCM3Tvarz38zlZM7Uc10.jpg"
    # )
    # db.session.add(new_movie)
    # db.session.commit()
    all_movies = Movie.query.all()
    return render_template("index.html", movies=all_movies)


if __name__ == '__main__':
    app.run(debug=True)

{% for movie in movies %}
<div class="card" >
  <div class="front" style="background-image: url('{{movie.img_url}}');">
    <p class="large">{{movie.ranking}}</p>
  </div>
  <div class="back">
    <div>
      <div class="title">{{movie.title}} <span class="release_date">({{movie.year}})</span></div>
      <div class="rating">
        <label>{{movie.rating}}</label>
        <i class="fas fa-star star"></i>
      </div>
      <p class="review">"{{movie.review}}"</p>
      <p class="overview">{{movie.description}}</p>

      <a href="#" class="button">Update</a>
      <a href="#" class="button delete-button">Delete</a>

    </div>
  </div>
</div>
{% endfor %}

{% for movie in movies %} 빼먹어서 조금 헤맸네 ㅎ;;

Edit a Movie's Rating and Review

index.html

<a href="{{url_for('edit', id=movie.id)}}" class="button">Update</a>

edit.html

{{ wtf.quick_form(form, novalidate=True) }}

class EditForm(FlaskForm):
    rating = StringField('Your Rating Out of 10 e.g. 7.5')
    review = StringField('Your review')
    submit = SubmitField('Done')

@app.route('/edit', methods=["GET", "POST"])
def edit():
    form = EditForm()
    movie_id = request.args.get('id')
    movie = Movie.query.get(movie_id)
    if form.validate_on_submit():
        movie.rating = float(form.rating.data)
        movie.review = form.review.data
        db.session.commit()
        return redirect(url_for('home'))
    return render_template('edit.html', form=form, movie=movie)

edit()작성하는게 고비였다..

Delete Movies from the Database

<a href="{{url_for('delete', id=movie.id)}}" class="button delete-button">Delete</a>

@app.route('/delete')
def delete():
    movie_id = request.args.get('id')
    movie_delete = Movie.query.get(movie_id)
    db.session.delete(movie_delete)
    db.session.commit()
    return redirect(url_for('home'))

Add New Movies Via the Add Page

class MovieForm(FlaskForm):
    title = StringField("Movie Title", validators=[DataRequired()])
    submit = SubmitField("Add Movie")


@app.route('/add', methods=["GET", "POST"])
def add():
    form = MovieForm()
    if form.validate_on_submit():
        params = {
            "api_key": API_KEY,
            "query": form.title.data,
        }
        response = requests.get(TMDB_endpoint, params=params)
        data = response.json()["results"]
        return render_template('select.html', movies=data)
    return render_template('add.html', form=form)
    

@app.route('/find')
def find():
    movie_api_id = request.args.get('id')
    if movie_api_id:
        movie_api_url = f"{MOVIE_DB_INFO_URL}/{movie_api_id}"
        response = requests.get(movie_api_url, params={"api_key": API_KEY})
        data = response.json()
        new_movie = Movie(
            title=data["title"],
            year=data["release_date"].split('-')[0],
            description=data["overview"],
            img_url=f"{MOVIE_DB_IMAGE_URL}{data['poster_path']}"
        )
        db.session.add(new_movie)
        db.session.commit()
        return redirect(url_for('edit', id=new_movie.id))

select.html

{% for movie in movies %}
<p>
  <a href="{{url_for('find', id=movie.id)}}"> {{movie.title}} - {{movie.release_date}}</a>
</p>
{% endfor %}

TMDB 페이지에서 값 호출해서 리스트업

리스트업 된 목록 중 하나 선택하면 edit으로 redirect한 후 값 입력하면 홈페이지에 추가됨.
(처음 코드 작성하고 리스트업 된 목록 알맞게 호출했을 때 감동,,,)

+) 제일 처음 db생성할 때 nullable=False으로 생성한 후에 nullable=True으로 수정했는데
수정해도 처음 생성했을때 nullable=False으로 물고와서 기존 db 파일 삭제하고 재생성함.

find()작성할 때 url_for 파라미터에 id=new_movie.id추가해야 edit()에서 id값 가져올 수 있음.

Sort and Rank the Movies By Rating

@app.route("/")
def home():
    all_movies = Movie.query.order_by(Movie.rating).all()
    for i in range(len(all_movies)):
        all_movies[i].ranking = len(all_movies) - i
    db.session.commit()
    return render_template("index.html", movies=all_movies)

아주 공감하는 바.....

hint보고 order_bymethod 사용할 거라는 건 알았지만 그걸 all()앞에 넣을줄은 몰랐습니다...

게다가 ranking을 raking이라고 적는 타이포오류까지,,, 휴

FINAL

https://gist.github.com/awesomekimn/d454ce28c10bf7b3c6fb6a14384e65ad

좋은 웹페이지 즐겨찾기