简体   繁体   中英

sqlalchemy.exc.OperationalError: (MySQLdb._exceptions.OperationalError) (1054, "Unknown column 'detail.id' in 'field list'")

I set up a small website, where anyone can store 'name,email,phone' but when I retrieve data from database so I'm getting this error. I don't why?

I'd spend two days to resolve this error but still I'm stuck with it.

sqlalchemy.exc.OperationalError: (MySQLdb._exceptions.OperationalError) (1054, "Unknown column 'detail.id' in 'field list'") [SQL: SELECT detail.id AS detail_id, detail.name AS detail_name, detail.email AS detail_email, detail.phone AS detail_phone, detail.date AS detail_date FROM detail] (Background on this error at: http://sqlalche.me/e/e3q8 )

My Code run.py :

from flask import Flask, render_template, request, redirect, url_for, session
from db import db
import datetime

# Every website is application in 'flask'
app = Flask(__name__, template_folder='template')
app.config['SQLALCHEMY_DATABASE_URI'] = 'mysql://root:''@localhost/flask' # 'test' is name of your database
# Database access through 'username'= root  and 'password'= None
# My username is 'root' cause I'm on the local host and I'd set any password
# One more thing password is after two dots :
app.config['SQLALCHEMY_TRACK_MODIFICATIONS'] = True



# database access
class detail(db.Model):
    def __init__(self, name, phone, email):
        self.name = name
        self.email = email
        self.phone = phone

    # table name as is it in your database
    __tablename__='detail'
    # give column names same as in your database otherwise it will give you error
    id = db.Column(db.Integer, primary_key=True)
    name = db.Column(db.String(20), nullable=False)
    email = db.Column(db.String(20), nullable=False)
    phone = db.Column(db.String(13), nullable=False)
    date=db.Column(db.DateTime, default=datetime.datetime.strftime(datetime.datetime.now(), '%d-%m-%Y   %I:%M:%S'))



# routing( setting end points in website) with ['post', 'get'] method
@app.route('/', methods=['POST', 'GET'])
def index():
    if request.method=='POST':
        name = request.form['name']
        email = request.form['email']
        phone = request.form['phone']

        try:
            # commit to add value in database
            data = detail(name=name, email=email, phone=phone)
            db.session.add(data)
            db.session.commit()

            # after commit redirect to this page
            return redirect(url_for('index'))

        except Exception as e:
            return e

    else:
        # retrieve data from database
        # here is problem
        data =  detail.query.all()  #<<<------------------------------- Error
        return render_template('index.html', data=data)




if __name__ == '__main__':
    # here we are telling to 'flask' that integrate db in 'app'
    db.init_app(app)
    # run flask app and you might be thinking debug mean that if you'll do any change in your application so it'll restart server auto
    app.run(debug=True)

My db.py file:

from flask import Flask
from flask_sqlalchemy import SQLAlchemy

'''here we are init. 'username ' and 'password' because if you'll config
this in your 'main.py application' so it'll not be work
so you have to keep it in a another file and import from there
'''
app = Flask(__name__)
app.config['SQLALCHEMY_DATABASE_URI'] = 'mysql://root:''@localhost/flask'
app.config['SQLALCHEMY_TRACK_MODIFICATIONS'] = True

db = SQLAlchemy(app)

My index.html file:

<!--
This is just a simple website it will add your 'name' and 'address', 'phone' in database
-->
<html>

<head>
  <title> First flaks app</title>
  <meta charset="utf-8">
  <meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no">
  <!-- Latest compiled and minified CSS -->
  <link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/4.3.1/css/bootstrap.min.css">

  <!-- jQuery library -->
  <script src="https://ajax.googleapis.com/ajax/libs/jquery/3.4.1/jquery.min.js"></script>

  <!-- Popper JS -->
  <script src="https://cdnjs.cloudflare.com/ajax/libs/popper.js/1.14.7/umd/popper.min.js"></script>

  <!-- Latest compiled JavaScript -->
  <script src="https://maxcdn.bootstrapcdn.com/bootstrap/4.3.1/js/bootstrap.min.js"></script>

  <script src="https://kit.fontawesome.com/f6cee5f9d4.js" crossorigin="anonymous"></script>
</head>

<body>
  <h1 class="text-warning text-center">Flask-app-connect to database</h1>
  <div class='container table-responsive w-50 mt-5'>
    <table class="table table-dark table-hover">
      <thead class='bg-info text-dark'>
        <tr>
          <th>Name</th>
          <th>Email</th>
          <th>Phone</th>
        </tr>
      </thead>
      {% for data in data %}
        <tbody>
          <tr>
            <td>{{data.Name}}</td>
            <td>{{data.Email}}</td>
            <td>{{data.Phone}}</td>
          </tr>
        </tbody>
      {% endfor %}
    </table>
  </div>

  <div class="container text-center mt-5">
    <!-- Trigger the modal with a button -->
    <button type="button" class="btn btn-info btn-sm" data-toggle="modal" data-target="#myModal">Add to
      database</button>

    <!-- Box Modal -->
    <div class="modal fade" id="myModal" role="dialog">
      <div class="modal-dialog">

        <!-- Modal content-->
        <div class="modal-content">
          <div class="modal-header">
            <h2>Add to database</h2>

          </div>
          <div class="modal-body">
            <!-- Form -->
            <form action="/" method="POST" role="form" class="was-validated">
              <div class="form-group">
                <input type="text" class="form-control" placeholder="Name" name="name" required>
                <div class="valid-feedback">Valid.</div>
              </div>
              <div class="form-group">
                <input type="email" class="form-control" placeholder="Email" name="email" required>
                <div class="valid-feedback">Valid.</div>
              </div>
              <div class="form-group">
                <input class="form-control" type="phone" placeholder="Phone" name="phone" required>
                <div class="valid-feedback">Valid.</div>
              </div>
              <button type="submit" class="btn btn-warning btn-spinner">Commit</button>
            </form>
            <!-- Form end -->
          </div>
          <div class="modal-footer">
            <button type="button" class="btn btn-default" data-dismiss="modal">Close</button>
          </div>
        </div>

      </div>
    </div>
    <!--End box modal-->

  </div>

</body>

</html>

I expect that:

How can I get all data from database and put it in index.html through loop.

Please, make me understand, where I'm doing mistake?

Understanding the error

The reason you are seeing this error is because as @moi mentioned your model and database don't match.

Your model has five attributes id , name , email , phone , and date . However, your database does not have a column called id in the detail table.

This causes an error when you query the database because SQLAlchemy specifies each column it is querying in the SELECT statement. In other words it says it wants the data from columns id , name , email , phone , and date . Unfortunatly, the database does not have a column called id , so it returns an error.

This was likely caused by you creating the model with out id and then adding it afterward. Thus you updated your model and not the database.

How to fix this

You need to get your database in sync with your model. You will need to run the following commands from your terminal.

First, install flask-migrate.

$ pip install Flask-Migrate

Second, configure flask-migrate

Read the Example section in the docs at a minimum for this. Flask Migrate Docs

Third, setup the migration folder.

$ flask db init

If this produces a Could not locate a Flask application. error. You will need to set the FLASK_APP environment variable. Replace run.py with the filename of your Flask app.

MacOS/Linux

$ export FLASK_APP=run.py

Windows

$ set FLASK_APP=run.py

Fourth, create your first migration.

$ flask db migrate

Once this is done you should find a new file xxxxxxxxxxxx_.py in your /migrations/versions directory. This is an Alembic migration file.

At this point you have three options.

Option 1 : you can drop your details table, and let flask-migrate create a fresh one. You will loose any data in it. Then run the upgrade command.

Option 2 : you can hand edit the new Alembic migration file. You will need to change the upgrade() function so it does not try to create a new details table since it already exists, but instead adds the id column.

Option 3 : you can delete the sa.Column("id" sa.Integer()... line from the upgrade() function as well as any other columns not in your database. Then manually create a table in your database called alembic_version with a single primary key VARCHAR column called version_num with a length 32. Then create a single entry in the alembic_version table with the value of the Revision ID from the alembic migration created above. Then run $ flask db migrate again. This will create a second alembic version file that should be able to upgrade your database.

Based on the state of your application and your level of experiance I would recommend option 1.

Fifth, upgrade your database.

$ flask db upgrade

Read the documentation

I highly recomend reading the documentation on both flask-migrate and Alembic. Flask-migrate is a well built wrapper for Alembic for flask appications.

Flask Migrate Docs

Alembic Docs

While inserting a varchar value, if you will forget to add single quotes, then this error will arise. Following is the error − mysql> insert into DemoTable798 values (100,Adam); ERROR 1054 (42S22): Unknown column 'Adam' in 'field list'

The following worked for me!

import pandas as pd
import sqlalchemy


engine = sqlalchemy.create_engine("mysql+pymysql://root:root@localhost/database name", pool_pre_ping=True)
# then specify the name of the table in the database
df = pd.read_sql_table('table name', engine)
print(df)

You can find the sqlalchemy documentations here

sqlalchemy.org

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM