All the project directory in zhuanlan.zhihu.com/p/113539585

In zhuanlan.zhihu.com/p/113371160, we build up the most basic homepage, now let us to realize the user login, registration link.

First, to get started, we need a database. Here I chose the MySQL database, specific can from blog.csdn.net/yangwei234/… (He is running Windows, and if he is on a Mac it will be the same, skipping the installation of Visual Studio.)

Once the database is configured, we need to connect to it. Here, too, I took a long time to configure, using PyMysql. First, let’s create a database. Open mysql terminal and type:

CREATE DATABASE <database-name>;
Copy the code

Replace the <database-name> in the MySQL terminal with your own database name, and then close the MySQL terminal and type the <database-name> in the command line

pip install flask-sqlalchemy
Copy the code

To install SQLAlchemy. Then, instantiate it in extensions.py:

from flask_bootstrap import Bootstrap  # import the Bootstrap - Flask
from flask_sqlalchemy import SQLAlchemy

bootstrap = Bootstrap()  # instantiate the extension
db = SQLAlchemy()

Copy the code

Now if you run the program, you might find a few warnings, but that’s because we haven’t set up the database yet. Now let’s set it up. Open the command line and type

pip install pymysql
Copy the code

To install Pymysql. Once installed, create config.py in the app folder to store all your Settings. Type in config.py:

import os


class DevelopmentConfig:
    DEBUG = True  Set to debug mode
    Set the database location
    SQLALCHEMY_DATABASE_URI = os.environ.get('DEV_DATABASE_URI') or 'mysql+pymysql://root:%s@localhost:3306/%s' \
                                                                    '? charset'\
                                                                    '=utf8mb4' % (os.environ.get('DEV_DATABASE_PASS'),
                                                                                  os.environ.get('DEV_DATABASE_NAME'))
    # Do not track changes
    SQLALCHEMY_TRACK_MODIFICATIONS = False


class ProductionConfig:
    DEBUG = False  # disable debugging
    Set up the database to use in the production environment
    SQLALCHEMY_DATABASE_URI = os.environ.get('DATABASE_URI') or 'mysql+pymysql://root:%s@localhost:3306/%s? charset' \
                               '=utf8mb4' % (os.environ.get('DATABASE_PASS'), os.environ.get('DATABASE_NAME'))
    SQLALCHEMY_TRACK_MODIFICATIONS = False


Set the config to be used in different cases
config = {
    'development': DevelopmentConfig,
    'production': ProductionConfig,

    'default': DevelopmentConfig
}

Copy the code

Now we can introduce it in init.py:

Import OS from flask import flask # Import flask from. Extensions import * # Import the instantiated extensions from app.config import config # Config def create_app(): Flask = Flask(__name__) # app.config.from_object(config[os.environ. Get ('FLASK_ENV')]) # Return app # Return appCopy the code

But that doesn’t work, because in config.py, we use two environment variables, so we need to define them before we run the program. But this is a problem, because the environment variable is only useful in the current session. However, we can simplify this by using python-dotenv. First, install it:

pip install python-dotenv
Copy the code

Then create a. Env file under the root directory to store environment variables:

FLASK_APP=app.py
DEV_DATABASE_PASS=<database-password>
DEV_DATABASE_NAME=<database-name>
Copy the code

Just replace <database-password> and <database-name> with your database password and name. Now when we run the program again, everything should be the same as before, because we haven’t created the table yet. Now create models.py under your app to store your database model: replace <database-password> and <database-name> with your database password and name. Now when we run the program again, everything should be the same as before, because we haven’t created the table yet. Now create models.py under your app to hold your database model:

SQLAlchemy class User(db.model): Db.model __tablename__ = 'users' # define tablename id = db.column (db.integer, primary_key=True) # define id, Column(db.string (64)) # email = db.column (db.string (128)) # email: def __repr__(self): Return '<User %s>' % self.usernameCopy the code

With the class created, we are now ready to update the database. I’m using flask-Migrate here to manage the version.

pip install flask-migrate
Copy the code

Initialization:

# app/extensions.py

from flask_bootstrap import Bootstrap  # import the Bootstrap - Flask
from flask_sqlalchemy import SQLAlchemy
from flask_migrate import Migrate

# instantiate the extension
bootstrap = Bootstrap()
db = SQLAlchemy()
migrate = Migrate()

Copy the code
# app/__init__.py # ... def create_app(): App = Flask(__name__) # create app instance app.config.from_object(config[os.environ. Get ('FLASK_ENV')]) # import Settings from config # initialize extension # . migrate.init_app(app, db) # ... Return app # Return appCopy the code

Now we initialize flask-migrate:

flask db init
Copy the code

At this point, an error occurs:

Traceback (most recent call last): File "/Users/sam/Desktop/Python/AttributeError/venv/bin/flask", line 10, in <module> sys.exit(main()) File "/ Users/Sam/Desktop/Python/AttributeError/venv/lib/python3.8 / site - packages/flask/cli. Py", line 966, in main cli.main(prog_name="python -m flask" if as_module else None) File "/ Users/Sam/Desktop/Python/AttributeError/venv/lib/python3.8 / site - packages/flask/cli. Py", line 586, in main return super(FlaskGroup, self).main(*args, * * kwargs) File "/ Users/Sam/Desktop/Python/AttributeError/venv/lib/python3.8 / site - packages/click/core. Py", line 782, in main rv = self.invoke(ctx) File "/ Users/Sam/Desktop/Python/AttributeError/venv/lib/python3.8 / site - packages/click/core. Py", line 1259, in invoke return _process_result(sub_ctx.command.invoke(sub_ctx)) File "/ Users/Sam/Desktop/Python/AttributeError/venv/lib/python3.8 / site - packages/click/core. Py", line 1259, in invoke return _process_result(sub_ctx.command.invoke(sub_ctx)) File "/ Users/Sam/Desktop/Python/AttributeError/venv/lib/python3.8 / site - packages/click/core. Py", line 1066, in invoke return ctx.invoke(self.callback, * * CTX. Params) File "/ Users/Sam/Desktop/Python/AttributeError/venv/lib/python3.8 / site - packages/click/core. Py", line 610, in invoke return callback(*args, * * kwargs) File "/ Users/Sam/Desktop/Python/AttributeError/venv/lib/python3.8 / site - packages/click/decorators. Py", line 21, in new_func return f(get_current_context(), *args, * * kwargs) File "/ Users/Sam/Desktop/Python/AttributeError/venv/lib/python3.8 / site - packages/flask/cli. Py", line 425, in decorator with __ctx.ensure_object(ScriptInfo).load_app().app_context(): The File "/ Users/Sam/Desktop/Python/AttributeError/venv/lib/python3.8 / site - packages/flask/cli. Py", line 388, in load_app app = locate_app(self, import_name, Name) File "/ Users/Sam/Desktop/Python/AttributeError/venv/lib/python3.8 / site - packages/flask/cli. Py", line 257, in locate_app return find_best_app(script_info, Module) File "/ Users/Sam/Desktop/Python/AttributeError/venv/lib/python3.8 / site - packages/flask/cli. Py", line 83, in find_best_app app = call_factory(script_info, App_factory) File "/ Users/Sam/Desktop/Python/AttributeError/venv/lib/python3.8 / site - packages/flask/cli. Py", line 119, in call_factory return app_factory() File "/Users/sam/Desktop/Python/AttributeError/app/__init__.py", line 12, In create_app app.config.from_object(config[os.environ. Get ('FLASK_ENV')]) # set KeyError: None to import from configCopy the code

This requires us to change one piece of code:

# app/__init__.py

#...


def create_app() :
    app = Flask(__name__)  # create app instance
    Import Settings from config, or default if the environment is not set
    app.config.from_object(config[os.environ.get('FLASK_ENV') or 'default'])

    #...

    return app  # to return to the app
Copy the code

Here, we set FLASK_ENV to import from default if it is None. Now initialize:

flask db init
Copy the code

You won’t get an error. A folder called Migrations should be created in the root directory to store changes to the database model. Now, to upgrade the database:

flask db migrate
Copy the code

“No changes in Schema detected. The reason for this is that flask-Migrate is determined by the import of files, and we have not introduced models.py in any of the files. Now create the auth folder in your app and create __init__.py:

# app/auth/__init__.py

from flask import Blueprint

auth = Blueprint('auth', __name__)

from . import views

Copy the code

Then, create views.py:

# app/auth/views.py

from . import auth
from app.models import User

Copy the code

Then, register auth blueprint:

# app/__init__.py # ... Def create_app(): Flask = Flask(__name__) Register_blueprint (main_bp) # Register blueprint to apply from.auth import auth as auth_bp App.register_blueprint (auth_bp) return app # Return appCopy the code

Now run flask db Migrate and you will be able to generate the update files. To make this file work, you need to update the database:

flask db upgrade
Copy the code

Now let’s test the database and open Flask’s interactive shell using flask shell:

Python 3.81. (v38.1.:1b293b6006, Dec 18 2019.14: 08:53) 
[Clang 6.0 (clang-600.057.)] on darwin
App: app [production]
Instance: /Users/sam/Desktop/Python/AttributeError/instance
>>> from app.models import User
>>> u = User(username='Test', email='[email protected]')  Create a user named Test
>>> from app.extensions import db
>>> db.session.add(u)  Add a user to this session
>>> db.session.commit()  Commit the changes to the database
>>> u
<User Test>
>>> u.username  Get user's username
'Test'
>>> u.email  Get the user's mailbox
'[email protected]'
>>> u.id  Get user id
1
>>> db.session.delete(u)  # delete user
>>> db.session.commit()
>>> User.query.all(a)Get all users
[]

Copy the code

You may find that in the current model, all users are equal and there is no administrator. Now, let’s solve this problem:

SQLAlchemy class Role(db.model): __tablename__ = 'role' id = db.Column(db.Integer, primary_key=True) name = db.Column(db.String(64)) users = db.relationship('User', backref='role', Lazy ='dynamic') # create an association def __repr__(self): return '<Role %s>' % self.name class User(db.model): Db.model __tablename__ = 'users' # define tablename id = db.column (db.integer, primary_key=True) # define id, Role_id = db.column (db.string (64)) # email = db.column (db.string (128)) # email = db.column (db.string (128)) # role_id = db.column (db.integer) Db.foreignkey (' role-id ')) def __repr__(self): return '<User %s>' % self.username # return <User %s>Copy the code

Let’s update the database:

flask db migrate -m "Added role"
INFO  [alembic.runtime.migration] Context impl MySQLImpl.
INFO  [alembic.runtime.migration] Will assume non-transactional DDL.
INFO  [alembic.autogenerate.compare] Detected added table 'role'
INFO  [alembic.autogenerate.compare] Detected added column 'users.role_id'
INFO  [alembic.autogenerate.compare] Detected added foreign key (role_id)(id) on table users
  Generating /Users/sam/Desktop/Python/AttributeError/migrations/versions/93740ecd2a4a_added_role.py ...  done

flask db upgrade
INFO  [alembic.runtime.migration] Context impl MySQLImpl.
INFO  [alembic.runtime.migration] Will assume non-transactional DDL.
INFO  [alembic.runtime.migration] Running upgrade 8f7a7e6cb8af -> 93740ecd2a4a, Added role
Copy the code

Now test it in the Flask shell:

Python 3.81. (v38.1.:1b293b6006, Dec 18 2019.14: 08:53) 
[Clang 6.0 (clang-600.057.)] on darwin
App: app [production]
Instance: /Users/sam/Desktop/Python/AttributeError/instance
>>> from app.models import Role, User
>>> from app.extensions import db
>>> admin = Role(name='Admin')
>>> db.session.add(admin)
>>> user = Role(name='Users')
>>> db.session.add(user)
>>> db.session.commit()
>>> # role.query.filter_by (name='Users').first(
>>> u1 = User(username='Test User', email='[email protected]', role=Role.query.filter_by(name='Users').first())
>>> db.session.add(u1)
>>> db.session.commit()
>>> u1.role
<Role Users>
>>> u2 = User(username='Test Admin', email='[email protected]', role=Role.query.filter_by(name='Admin').first())
>>> db.session.add(u2)
>>> db.session.commit()
>>> u2.role
<Role Admin>
>>> admin.users.all()
[<User Test Admin>]
>>> user.users.all()
[<User Test User>]
Copy the code

Well, that’s it for today. I have put the code at github.com/PythonSamZh… Git checkout ef00826 to checkout this version, create a.env file, fill in the environment variables, and perform the flask db upgrade.

Write in the last

This is the second article in this series, because I am also a little white, so if there is something wrong, please kindly advise me