Build a CRUD App with SQLAlchemy - update

Update: Set the attributes of an existing object in the database.

SQL 语句

UPDATE table_name
SET column1 = value1, column2 = value2, ...
WHERE condition;

SQLAlchemy ORM

user = User.query.get(some_id)
user.name = 'Some new name'
db.session.commit()

The if statement in Jinja.

{
    
    % if users %}
<ul>
{
    
    % for user in users %}
	<li>
		{
    
    {
    
     user.username|e }}
	</li>
{
    
    % endfor %}
</ul>
{
    
    % endif %}
{
    
    % if users %}
	Kenny is sick
{
    
    % elif kenny.health %}
	Kenny is health
{
    
    % else %}
	Keeny looks okay
{
    
    % endif %}

Jinja Docs


<!DOCTYPE html>
<html>
    <head>
        <title>Todo app</title>
        <style>
            .hidden {
      
      
                display:none;
            }

            ul {
      
      
                list-style: none;
                padding: 0;
                margin: 0;
            }
        </style>
    </head>
    <body>
        <form id="form">
            <input type="text" id="description" name="description" />
            <input type="submit" value="Create" />
        </form>
        <div id="error" class="hidden">Something went wrong!</div>
        <ul id="todos">
            {% for d in data %}
                <li>
                    <input class="check-completed" data-id="{
     
     { d.id }}" type="checkbox" {% if d.completed %} checked {% endif %} />
                        {
   
   { d.description }}
                </li>
            {% endfor %}
        </ul>
        <script>
            // Loop over all of these checkbox elements and listen to the change event with a on change function.
            const checkboxes = document.querySelectorAll('.check-completed');
            for (let i = 0; i < checkboxes.length; i++) {
      
      
                const checkbox = checkboxes[i];
                checkbox.onchange = function(e) {
      
      
                    console.log('event', e);
                    const newCompleted = e.target.checked;
                    const todoId = e.target.dataset['id'];
                    fetch('/todos/' + todoId + '/set-completed', {
      
      
                        method: 'POST',
                        body: JSON.stringify({
      
      
                            'completed': newCompleted
                        }),
                        headers: {
      
      
                            'Content-Type': 'application/json'
                        }
                    })
                    .then(function() {
      
      
                        document.getElementById('error').className = 'hidden';
                    })
                    .catch(function() {
      
      
                        document.getElementById('error').className = '';
                    })
                }
            }


            // Select on the form
            // onsubmit handler to default wound up sending information to the server
            // Using the event object, e
            document.getElementById('form').onsubmit = function(e) {
      
      
                // The default behaviro would have done that full page refresh and 
                // submitted it using the method and action attributes up
                e.preventDefault();

                // Send the post requests asynchronously using fetch
                fetch('/todos/create', {
      
      
                    method: 'POST',
                    body: JSON.stringify({
      
      
                        // The value of whatever the user has typed into the description field.
                        'description': document.getElementById('description').value
                    }),
                    headers: {
      
      
                        'Content-Type': 'application/json'
                    }
                })
                // give back a promise by which we can then use the 
                // then method
                // callback should give us back a response
                .then(function(response) {
      
      
                    // parse out the response which will initially be a string as a JSON response
                    return response.json();
                })
                // manipulate the JSON response 
                .then(function(jsonResponse) {
      
      
                    console.log(jsonResponse);
                    // Append a child Li element here
                    const liItem = document.createElement('LI');
                    liItem.innerHTML = jsonResponse['description'];
                    document.getElementById('todos').appendChild(liItem);
                    // it did succeed
                    document.getElementById("error").className = 'hidden';
                })
                // catch handler
                .catch(function() {
      
      
                    // Remove the class name
                    document.getElementById("error").className = '';
                })
            }
        </script>
    </body>
</html>
from flask import Flask, render_template, request, redirect, url_for, jsonify
from flask_sqlalchemy import SQLAlchemy
import sys
from flask_migrate import Migrate

app = Flask(__name__)
app.config['SQLALCHEMY_DATABASE_URI'] = 'postgres://username@localhost:5432/todoapp'
db = SQLAlchemy(app)

# Link to Flask app as well as the SQLAlchemy database
# migrate will do is start it up so that we can start using the Flask databae migrate commands to began initializing migrations
# and upgrading and downgrading and generating migrations as well.
migrate = Migrate(app, db)

class Todo(db.Model):
    __tablename__ = 'todos'
    id = db.Column(db.Integer, primary_key=True)
    description = db.Column(db.String(), nullable=False)
    completed = db.Column(db.Boolean, nullable=False, default=False)

    def __repr__(self):
        return f'<Todo {
      
      self.id} {
      
      self.description}>'

# Ensure the tables are created for all the models that we've created and they haven't been created.
# db.create_all()

@app.route('/todos/create', methods=['POST'])
def create_todo():
    error = False
    body = {
    
    }
    try:
        # get_json is that it fetches the JSON body that was sent to an object key description.
        description = request.get_json()['description']
        todo = Todo(description=description)
        db.session.add(todo)
        db.session.commit()
        body['description'] = todo.description
    except:
        error = True
        db.session.rollback()
        # debugging sentence
        print(sys.exc_info())
    finally:
        db.session.close()
    if not error:
        # return a useful JSON object that includes that description.
        # jsonify will return JSON data to the client for us.
        # whatever we pass in as our JSON object.
        return jsonify(body)

@app.route('/todos/<todo_id>/set-completed', methods=['POST'])
def set_completed_todo(todo_id):
    try:
        completed = request.get_json()['completed']
        print('completed', completed)
        todo = Todo.query.get(todo_id)
        todo.completed = completed
        db.session.commit()
    except:
        db.session.rollback()
    finally:
        db.session.close()
    return redirect(url_for('index'))



@app.route('/')
def index():
    return render_template('index.html', data=Todo.query.order_by('id').all())

运行命令:

$ FLASK_APP=app.py FLASK_DEBUG=true flask run

在网页中,点击check了之后,刷新页面,数据还在网页上,因为数据已经存储在数据库里

Guess you like

Origin blog.csdn.net/BSCHN123/article/details/121493059