如何在烧瓶中实现按钮而不渲染模板?

时间:2020-07-01 14:29:39

标签: python flask jinja2

我是Python和Flask的新手,从rn开始,我正在尝试建立一个网站,通过按一下按钮生成随机颜色,但是您可以将这些随机颜色保存在个人资料中然后再进行管理(删除,四处移动等)。

我现在面临的问题是在我的“随机”页面上,我似乎无法弄清楚如何在不呈现整个页面的情况下实现保存按钮,从而再次使颜色随机化,因此将错误的颜色“保存”到数据库中。这是我到目前为止的内容:

app.py

@app.route("/l_randomize", methods=["GET", "POST"])
def l_randomize():
if request.method == "GET":
    return render_template("l_randomize.html")
else:
    color = '#{:02x}{:02x}{:02x}'.format(*random.sample(range(256), 3))
    if 'favourite' in request.form:
        db.execute("INSERT INTO fav (user_id, color) VALUES (:user_id, :color)", user_id=session["user_id"], color=color)
    return render_template("l_randomized.html",color=color)

app.html

{%block body%}
<div class="container">
<h3>Your color is</h3>
<div id="l_randomized" style="background-color: {{ color }};">
<form method="post" action="/l_randomize">
    <input type="submit" name = "randomize" value="Randomize" >
    <input type="submit" name = "favourite" value="Favourite" >
</form>
</div>
</div>
{%endblock%}

我有点理解我已经编写的代码中的缺陷以及为什么它会再次呈现该模板,但是我只需要一个提示或要看的地方,因此在 if语句之后,它不会t刷新页面或继续。高度赞赏有关如何更好地实施此功能的任何建议,评论和提示!

1 个答案:

答案 0 :(得分:1)

这比您想象的要复杂得多。您将需要使用某种异步更新。在这种情况下,如果不学习React ,使用JQuery可能会更容易。本质上,您想拦截表单提交以保存喜欢的颜色(请注意,我在英国,所以下面的示例中我的拼写可能不一致,抱歉),然后仅更改DOM中的特定元素。

下面有很多代码,但这是一个独立的示例-只需运行脚本并转到127.0.0.1:5000。主要变化:

  1. 我已切换到Flask-SQLAlchemy ORM(对象关系映射器)。部分原因是因为对我来说,建立一个最小的示例比较容易,但是在应用程序开发中通常也更容易。因此,我制作了两个类来为您创建数据库表。
  2. 我已经实现了两个使用AJAX的JavaScript函数。一个附加到按钮单击上,另一个则拦截表单提交。
  3. 我将Flask路线分开,以便可以分别处理不同的事件

本质上:

  1. 如果我们不知道用户喜欢的颜色,我们将给出白色背景。
  2. 如果他们随机选择一种新颜色,我们将仅更新背景颜色 。我们还将在表单中更新一个隐藏字段,以保留其首选项,以防他们想要保留该字段。
  3. 如果他们单击“收藏夹”,我们会将其写入数据库。如果您关闭页面并在此之后再次打开它,您会注意到我们加载了他们先前的收藏夹

不要在您的实际代码中使用render_template_string,它只是允许我将模板放入单个脚本中。

这仅用于说明目的。目的是在常规设置上连接点。它缺少诸如表单验证之类的东西。

from flask import Flask, render_template_string, session, request
from flask_sqlalchemy import SQLAlchemy

import random

# =============================================================================
# BASIC APP INIT
# =============================================================================
db = SQLAlchemy()

app = Flask('__main__')
app.config['SQLALCHEMY_DATABASE_URI'] = 'sqlite:///test.db'
app.config['SECRET_KEY'] = 'change_me'
db.init_app(app)

# =============================================================================
# DATABASE MODELS
# =============================================================================
class Users(db.Model):
    id = db.Column(db.Integer, primary_key=True)
    username = db.Column(db.String)
    

class Fav(db.Model):
    id = db.Column(db.Integer, primary_key=True)
    user_id = db.Column(db.Integer, db.ForeignKey('users.id')) 
    color = db.Column(db.String)

with app.app_context():
    db.create_all()

    user = Users(username='testing') # Create a fake user
    db.session.add(user)
    db.session.commit()

# =============================================================================
# TEMPLATE
# =============================================================================

l_randomize_html = """
{%block body%}
<div class="container">
   <h3>Your color is</h3>
   <div id="l_randomized" style="background-color: {{ color }};">
      <button onclick="changeColor()">Change</button>
      <form method="post" action="{{ url_for('l_save_favourite') }}" id="favColorForm">
         <input type="hidden" name="currentColor" id="currentColor" value="{{ color }}">
         <input type="submit" name="favourite" value="Favourite" >
      </form>
      <div id="colorSaveResp"></div>
   </div>
</div>
<script src="https://code.jquery.com/jquery-3.5.1.min.js"></script>
<script>
   function changeColor() {
       $.ajax({
           type: 'POST',
           url: "{{ url_for('change_color') }}",
           success: function(color) {
               $("#currentColor").val(color);
               $("#l_randomized").css("backgroundColor", color);
           }
       });
   }
</script>
<script>
   $("#favColorForm").submit(function(e) {
       e.preventDefault();
       var form = $(this);
       var url = form.attr('action');
    
       $.ajax({
           type: "POST",
           url: url,
           data: form.serialize(),
           context: form,
           success: function(resp) {
               $("#dynamic_div").html(resp);    
           }
       });
   });
</script>
{%endblock%}
"""

# =============================================================================
# ROUTES
# =============================================================================

@app.route('/', methods=['GET'])
def l_randomize():
    session['user_id'] = 1 # Add to the session
    # See whether we have a favourite colour 
    favourite = Fav.query.filter_by(user_id=session['user_id']).first()
    if favourite:
        color = favourite.color
    else:
        # They don't, give a default
        color = '#FFF' 
    return render_template_string(l_randomize_html, color=color)


@app.route('/change_color', methods=['POST'])
def change_color():
    return '#{:02x}{:02x}{:02x}'.format(*random.sample(range(256), 3))


@app.route('/save_color', methods=['POST'])
def l_save_favourite():
    data = request.form.to_dict()
    
    favourite = Fav.query.filter_by(user_id=session['user_id']).first()
    if not favourite:
        # We don't know this user's favourite colour yet, add it
        favourite = Fav(user_id=session['user_id'],
                        color=data['currentColor'])
        db.session.add(favourite)
        db.session.commit()
    else:
         # We'll update their favourite
        favourite.color = data['currentColor']
    db.session.commit()
    return "Saved"


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

这里有很多东西,还有很多可以实现的东西,但是已经太久了。希望您可以运行它并逐一处理各个点。