2024年1月10日 星期三

10大最愛電影小專案(CRUD)之排版炸裂 V3

 注意: 這個小專案 曾經犯個錯誤導致css無法載入,靜態檔案當中的static 打成statics導致無法載入





main.py

from flask import Flask,redirect,render_template,request,url_for
from flask_wtf import FlaskForm
from wtforms import StringField,SubmitField,SelectField,SearchField,TextAreaField,DateTimeField,FloatField,IntegerField,URLField
from wtforms.validators import DataRequired,URL,NumberRange
from flask_bootstrap import Bootstrap5
from flask_sqlalchemy import SQLAlchemy
from sqlalchemy import desc
from datetime import datetime


#建立資料庫與綁定flask
app = Flask(__name__)
Bootstrap5(app)
#建立bootstrap5


#建立密鑰,防止CSRF
app.secret_key="jdklasjdosaudioasudoaskk;k;jdsauiudwq"

#建立一個SQLAlchemy實例
db =SQLAlchemy()
#配置給Flask,如果不存在就會建立這個db
app.config['SQLALCHEMY_DATABASE_URI']="sqlite:///movie.db"
#將db綁定給Flask使用
db.init_app(app)
#init_app方法主要作用是將擴展配置綁定到Flask應用程式

#建立模式
class Movie(db.Model):
    id = db.Column(db.Integer,primary_key=True,autoincrement=True)
    name = db.Column(db.String(256),unique=True,nullable=False)
    msg = db.Column(db.String(256),nullable=False)    
    ranking = db.Column(db.Integer,unique=True,nullable=False)
    rating = db.Column(db.String(256),nullable=False)
    img_url = db.Column(db.String(256),nullable=False)
    # created_at = db.Column(db.DateTime, default=datetime.utcnow,nullable=False)
    created_at = db.Column(db.DateTime,nullable=False)
    #這邊得default 接受可呼叫的對象, 而不是實際的函數調用

#建立上面定義的模型建立資料表
with app.app_context():
    db.create_all()    


class MyForm(FlaskForm):
    name = StringField("電影名稱",validators=[DataRequired()])
    msg = TextAreaField("劇情大綱:",validators=[DataRequired()])
    ranking = SelectField("排名",choices=[str(i) for i in range(1,11)],validators=[DataRequired()])
    rating = SelectField("評分",choices=['⭐','⭐⭐','⭐⭐⭐','⭐⭐⭐⭐','⭐⭐⭐⭐⭐'],validators=[DataRequired()])
    date = DateTimeField("上映日期 (YYYY-MM-DD)",format='%Y-%m-%d',validators=[DataRequired()])
    img_url = URLField('電影圖片網址',validators=[DataRequired(),URL()])
    sumbit = SubmitField("新增電影")
    #每次選擇排名後就排除選項
    def __init__(self,*args,**kwargs):
        #這邊因為重新定義子類別__init__,但我需要父類別邏輯,所以使用super()
        '''
        在上述代碼中,super(MyForm, self).__init__(*args, **kwargs) 調用了 FlaskForm 類的 __init__ 方法,並傳遞了 *args 和 **kwargs。
        這麼做確保了 FlaskForm 中的初始化邏輯得以執行,同時允許 MyForm 在其自己的 __init__ 方法中添加額外的初始化邏輯。
        '''
        super(MyForm, self).__init__(*args, **kwargs)
        used_rankings=[str(movie.ranking) for movie in Movie.query.all()]
        print(f'used={used_rankings}')
        available_ranking = [str(i) for i in range(1,11) if str(i) not in used_rankings]
        print(f'我可以用={available_ranking}')
         # Update the 'ranking' field choices
        self.ranking.choices = available_ranking


@app.route('/')
def home():
    #讀取db    
    with app.app_context():
        db_rows = Movie.query.order_by(desc(Movie.ranking)).all()
   
   
    return render_template('index.html',rows=db_rows)



@app.route('/add',methods=['POST','GET'])
def add():
    form=MyForm()
    print(f'ranking={form.ranking.choices}')
    if form.validate_on_submit():
        new_movie = Movie(
            name=form.name.data,
            msg=form.msg.data,
            ranking=form.ranking.data,
            rating=form.rating.data,
            created_at=form.date.data,
            img_url=form.img_url.data)
        db.session.add(new_movie)
        db.session.commit()
        return redirect(url_for('home'))  


    return render_template('add_movie.html',form=form)




@app.route('/edit',methods=['GET','POST'])
def edit():
    id = request.args.get('id')
   
    with app.app_context():
        result=db.session.execute(db.select(Movie).where(Movie.id==id)).scalar()
        print(f'result= {result.name}')
        if request.method=='POST':
            action = request.form.get('action')
            print(f"action={action}")
            if action == 'del_movie':
                moive_del=db.get_or_404(Movie,id)
                db.session.delete(moive_del)
                db.session.commit()
                return redirect(url_for('home'))

            print('表單提交')
            new_rating =request.form.get('new_rating')
            if not new_rating.strip() :
                print("沒有輸入表單,使用預設值⭐")
                new_rating='⭐'
            movie_update=db.get_or_404(Movie,id)
            movie_update.rating = new_rating
            db.session.commit()
            request.form.get('action')


           
        return render_template('edit.html',row=result)
   





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

base.html

<!DOCTYPE html>
<html lang="zh">
<head>
   
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>
        {% block title %}
        昆之電影庭園
        {% endblock %}
    </title>
    {% block styles %}
    <link href="https://cdn.jsdelivr.net/npm/bootstrap@5.3.2/dist/css/bootstrap.min.css" rel="stylesheet" integrity="sha384-T3c6CoIi6uLrA9TneNEoa7RxnatzjcDSCmG1MXxSR1GAsXEV/Dwwykc2MPK8M2HN" crossorigin="anonymous">

    <!-- {{bootstrap.load_css()}} -->
    <link rel="stylesheet" href="{{ url_for('static', filename='css/styles.css') }}">

    {% endblock %}
</head>
<body>
    {% block content %}
   
    {% endblock %}
    {% block scripts %}
        {{bootstrap.load_js()}}
    {% endblock %}

</body>
</html>
{% extends "base.html" %}




{% block content %}
<h1>My favorite Top 10 Movie</h1>

{% for row in rows %}

<div class="card container text-white bg-dark mb-3" style="max-width: 36rem;">
  <img src="{{row.img_url}}" class="card-img-top mt-3" alt="...">
  <div class="card-body">
    <h5 class="card-title">{{row.name}}</h5>
    <p class="card-text">{{row.msg}}</p>
    <p class="card-text"><small class="text-muted">排名:{{row.ranking}}</small></p>
    <a href="{{url_for('edit',id=row.id)}}" class="btn btn-primary">編    輯</a>
   
  </div>
</div>



<br>
{% endfor %}


<a href="{{url_for('add')}}" class="fixed-link-index">新 增 </a>
{% endblock %}

---add_moive.html

{% extends "base.html" %}
{% from 'bootstrap5/form.html' import render_form %}
{% block title%}
新增電影
{% endblock %}
{% block content %}
<div class="container">
    <div class="row">
        <div class="col-sm-12 col-md-8">

            {{render_form(form, novalidate=True)}}
        </div>
    </div>
</div>


{% endblock %}

---edit.html

{% extends "base.html" %}
{% block title %}
{{row.name}}
{% endblock %}
{% block content %}
<div class="container shadow-lg p-3 mb-5 bg-body rounded ">
<table class="table table-dark table-striped table-hover">
    <tbody >


    <tr>
        <td>{{row.name}}</td>
    </tr>
    <tr>
        <td>{{row.msg}}</td>
    </tr>
    <tr>
        <td>{{row.rating}}</td>
    </tr>    

    </tbody>
</table>
    <br>
    <form action="" method="post">
        <label for="">新評價:</label>

        <input type="text" placeholder="⭐" class="form-control" name="new_rating">

        <button type="submit" class="btn btn-secondary">確 認 修 改</button>

        <button type="submit" class="btn btn-danger" name="action" value="del_movie">刪    除</button>

</form>
<br>
<a href="{{url_for('home')}}" class="btn-primary"> 回 首 頁</a>
</div>

{% endblock %}


標籤: ,

0 個意見:

張貼留言

訂閱 張貼留言 [Atom]

<< 首頁