Ich mache eine Web-App mit Flask und habe Code, der wiederverwendet werden kann, also werde ich ihn teilen. Wir haben nicht erwähnt, welcher Code welche Funktionen bietet. Bitte recherchieren Sie selbst.
Installieren Sie die diesmal zu verwendende Erweiterung im Voraus. Sie müssen die Version nicht angeben, da die neuesten Versionen vorbereitet werden.
requirements.txt
Flask
Flask-Login
Flask-Migrate
Flask-SQLAlchemy
Flask-WTF
SQLAlchemy
Werkzeug
WTForms
Jinja2
email-validator
pip install -r requirements.txt
Flask verwendet so etwas wie "Blueprint", um die Funktionalität zu teilen.
├───main.py # main app.py file to be called to start server for web app
├───requirements.txt # File of pip install statements for your app
├───migrations # folder created for migrations by calling
├───myproject # main project folder, sub-components will be in separate folders
│ │ data.sqlite
│ │ models.py
│ │ __init__.py
│ │
│ │───auth
│ │ │ forms.py
│ │ │ views.py
│ │ │
│ │ │───templates
│ │ │ └───auth
│ │ │ login.html
│ │ │ signup.html
│ │
│ ├───static # Where you store your CSS, JS, Images, Fonts, etc...
│ ├───templates
│ base.html
│ home.html
In dieser Konfiguration enthält "__init __. Py" "config", Sie können es jedoch als "config.py" trennen.
Wir haben ein gemeinsames Layout für "base.html" vorbereitet und es als "{{% erweitert" base.html "%}}" unter Verwendung einer Vorlagen-Engine namens "jinja2" ("layout") wiederverwendet. Der Name hmtl` wird auch häufig verwendet).
Ich verwende "SQLite" für SQL, kann es jedoch nicht für "Heroku" bereitstellen und es ist nicht für die Skalierung geeignet. Wenn Sie also SQL verwenden, ist es besser, tatsächlich "MySQL" oder "PostgreSQL" zu verwenden. Ich denke. Da wir "ORM" mit dem Namen "SQLAlchemy" verwenden, um die Datenbank zu verwalten, kann derselbe Code verwendet werden, auch wenn SQL anders ist (das Setup ist anders). data.sqlite`` migrations
ist eine von Ihnen selbst erstellte Datei / ein Ordner.
Es ist eine Anforderung von "Blueprint", eine redundante Struktur wie "myproject \ auth \ templates \ auth" zu haben.
In "auth \ forms.py" werden die Anmelde- und Anmeldeformulare empfangen, und in "auth \ views.py" werden die aus den Formularen eingegebenen Daten empfangen, verarbeitet und gerendert.
main.py
und __ init __. py
Da main.py nur Anrufe tätigt, sieht es folgendermaßen aus:
main.py
from flask import render_template
from myproject import app
@app.route('/')
def index():
return render_template('home.html')
if __name__ == '__main__':
app.run(debug=True)
Diese Datei registriert sich bei config und blueprint und führt die gesamte Initialisierung durch.
__init__.py
import os
from flask import Flask, redirect, url_for
from flask_sqlalchemy import SQLAlchemy
from flask_migrate import Migrate
from flask_login import LoginManager
login_manager = LoginManager()
app = Flask(__name__, static_folder='static', template_folder='templates')
basedir = os.path.abspath(os.path.dirname(__file__))
#Wenn Sie das Heroku Postgres-Add-On hinzufügen, wird die Umgebungsvariable DATABASE hinzugefügt_Zur URL
#Dieser Wert wird festgelegt, da die Verbindungsziel-URL der PostgreSQL-Datenbank festgelegt ist.
#Wenn eingestellt(Beim Laufen auf Heroku)Benutze es,
#Wenn nicht eingestellt(Lokales Debuggen usw.)Ermöglicht die Verwendung der lokalen SQLite-Datenbank.
SQLALCHEMY_DATABASE_URI = os.environ.get('DATABASE_URI') or 'sqlite:///' + os.path.join(basedir, 'data.sqlite')
app.config['SECRET_KEY'] = 'mysecretkey'
app.config['SQLALCHEMY_DATABASE_URI'] = SQLALCHEMY_DATABASE_URI
app.config['SQLALCHEMY_TRACK_MODIFICATIONS'] = False
db = SQLAlchemy(app)
Migrate(app, db)
#Stellen Sie sicher, dass Sie hier importieren, nachdem Sie die Definition von db abgeschlossen haben
from myproject.auth.views import auth_blueprint
app.register_blueprint(auth_blueprint, url_prefix='/authenticate')
login_manager.init_app(app)
login_manager.login_view = "auth.login"
Die letzte Zeile "login_manager.login_view =" auth.login "" bezieht sich auf den Anmeldebildschirm, der umgeleitet wird, wenn Sie versuchen, darauf zuzugreifen, obwohl "@ login_required" vorhanden ist.
Wenn Sie beispielsweise versuchen, zu "\ logout" zu wechseln, während Sie nicht angemeldet sind, wird die in "views.py" definierte Anmeldefunktion aufgerufen (da der Anmeldebildschirm durch die Rückkehr der Funktion gerendert wird, wechseln Sie zu diesem Bildschirm. Masu).
Die Tabelle ist in models.py
definiert. Ich behalte meinen Benutzernamen, meine E-Mail-Adresse und mein Hash-Passwort.
Abgesehen davon ist der Grund, warum die Schaltfläche "Passwort vergessen?" Das Passwort nicht anzeigt, dass es überhaupt nicht in der Datenbank verbleibt, sodass Sie es nicht sagen können.
models.py
from werkzeug.security import generate_password_hash, check_password_hash
from flask_login import UserMixin
from myproject import db, login_manager
@login_manager.user_loader
def load_user(user_id):
return User.query.get(user_id)
class User(db.Model, UserMixin):
__tablename__ = 'users'
id = db.Column(db.Integer, primary_key = True)
username = db.Column(db.String(64), unique=True, index=True)
email = db.Column(db.String(64), unique=True, index=True)
password_hash = db.Column(db.String(128))
def __init__(self, email, username, password):
self.email = email
self.username = username
self.password_hash = generate_password_hash(password)
def check_password(self,password):
return check_password_hash(self.password_hash, password)
Es ist für die allgemeine Benutzeranmeldung vorgesehen. Der Nutzer
Geben Sie die.
Erstens ist das Anmeldeformular.
forms.py
from flask_wtf import FlaskForm
from wtforms import StringField, PasswordField, SubmitField
from wtforms.validators import DataRequired,Email,EqualTo
class SignupForm(FlaskForm):
email = StringField('Email', validators=[DataRequired(),Email()])
username = StringField('Username', validators=[DataRequired()])
password = PasswordField('Password', validators=[DataRequired(), EqualTo('pass_confirm', message='Passwords Must Match!')])
pass_confirm = PasswordField('Confirm password', validators=[DataRequired()])
submit = SubmitField('Sign Up')
Als nächstes folgt die interne Verarbeitung. Der Benutzername und die E-Mail-Adresse dürfen sich in der Datenbank nicht überschneiden. Wenn sie in der Datenbank übereinstimmen, wird ein Fehler ausgegeben und Sie werden aufgefordert, sie erneut einzugeben.
Wenn Sie sich erfolgreich angemeldet haben, werden Sie zum Anmeldeformular weitergeleitet.
views.py
from flask import (Blueprint, render_template,
redirect, url_for, request,
flash, abort)
from flask_login import login_user, login_required, logout_user, current_user
from werkzeug.security import generate_password_hash, check_password_hash
import os
import sys
sys.path.append(os.path.join(os.path.dirname(__file__), '..'))
from myproject import db, app
from myproject.models import User
from myproject.auth.forms import LoginForm, SignupForm
auth_blueprint = Blueprint('auth',
__name__,
template_folder='templates/auth')
@auth_blueprint.route('/signup', methods=['GET', 'POST'])
def signup():
form = SignupForm()
if form.validate_on_submit():
if User.query.filter_by(email=form.email.data).first():
flash('Email has been registered already!')
redirect(url_for('auth.signup'))
elif User.query.filter_by(username=form.username.data).first():
flash('Username has been registered already!')
redirect(url_for('auth.signup'))
else:
user = User(email=form.email.data,
username=form.username.data,
password=form.password.data)
db.session.add(user)
db.session.commit()
flash('Now You can login!')
return redirect(url_for('auth.login'))
return render_template('signup.html', form=form)
Es wird davon ausgegangen, dass sich ein allgemeiner Benutzer anmeldet.
Der Benutzer gibt eine E-Mail-Adresse und ein Passwort ein. Es wird in derselben Datei wie das Anmeldeformular beschrieben.
forms.py
from flask_wtf import FlaskForm
from wtforms import StringField, PasswordField, SubmitField
from wtforms.validators import DataRequired,Email,EqualTo
class LoginForm(FlaskForm):
email = StringField('Email', validators=[DataRequired(), Email()])
password = PasswordField('Password', validators=[DataRequired()])
submit = SubmitField('Log In')
class SignupForm(FlaskForm):
email = StringField('Email', validators=[DataRequired(),Email()])
username = StringField('Username', validators=[DataRequired()])
password = PasswordField('Password', validators=[DataRequired(), EqualTo('pass_confirm', message='Passwords Must Match!')])
pass_confirm = PasswordField('Confirm password', validators=[DataRequired()])
submit = SubmitField('Sign Up')
Als nächstes folgt die interne Verarbeitung. Identifizieren Sie den Benutzer anhand der E-Mail-Adresse. Das Passwort wird mit dem Passwort-Hash-Wert des Benutzers verglichen, indem die in models.py
gespielte Funktion check_password
verwendet wird.
Wenn Sie sich erfolgreich angemeldet haben, können Sie zu einem beliebigen Ort springen.
Übrigens werde ich auch den Abmeldevorgang verlassen.
views.py
from flask import (Blueprint, render_template,
redirect, url_for, request,
flash, abort)
from flask_login import login_user, login_required, logout_user, current_user
from werkzeug.security import generate_password_hash, check_password_hash
import os
import sys
sys.path.append(os.path.join(os.path.dirname(__file__), '..'))
from myproject import db, app
from myproject.models import User
from myproject.auth.forms import LoginForm, SignupForm
auth_blueprint = Blueprint('auth',
__name__,
template_folder='templates/auth')
@auth_blueprint.route('/logout')
@login_required
def logout():
logout_user()
flash('You logged out!')
return redirect(url_for('index'))
@auth_blueprint.route('/login', methods=['GET', 'POST'])
def login():
form = LoginForm()
if form.validate_on_submit():
user = User.query.filter_by(email=form.email.data).first()
if user is None:
flash('something wrong!')
redirect(url_for('auth.login'))
elif user.check_password(form.password.data):
login_user(user)
flash('Logged in successfully.')
# login => somewhere
return redirect(url_for('somewhere'))
else:
pass
return render_template('login.html', form=form)
@auth_blueprint.route('/signup', methods=['GET', 'POST'])
def signup():
form = SignupForm()
if form.validate_on_submit():
if User.query.filter_by(email=form.email.data).first():
flash('Email has been registered already!')
redirect(url_for('auth.signup'))
elif User.query.filter_by(username=form.username.data).first():
flash('Username has been registered already!')
redirect(url_for('auth.signup'))
else:
user = User(email=form.email.data,
username=form.username.data,
password=form.password.data)
db.session.add(user)
db.session.commit()
flash('Now You can login!')
return redirect(url_for('auth.login'))
return render_template('signup.html', form=form)
flash () wird wie folgt empfangen.
example.html
{% with messages = get_flashed_messages() %}
{% if messages %}
{% for message in messages %}
{{ message }}
{% endfor %}
{% endif %}
{% endwith %}
Möglicherweise möchten Sie die Anzeige vor und nach dem Anmeldestatus ändern. Wenn Sie sich beispielsweise anmelden, wird eine Schaltfläche zum Abmelden angezeigt.
In diesem Fall können Sie "current_user.is_authenticated" für die bedingte Verzweigung verwenden.
example.html
{% if current_user.is_authenticated %}
<a class="nav-item nav-link" href="#">{{ current_user.username }}</a>
<a class="nav-item nav-link" href="{{ url_for('task.scheduletoday') }}">Der heutige Zeitplan</a>
<a class="nav-item nav-link" href="{{ url_for('task.alltasks')}}">Aufgabenliste</a>
<a class="nav-item nav-link" href="{{ url_for('auth.logout') }}">Ausloggen</a>
{% else %}
<a class="nav-item nav-link" href="{{ url_for('auth.login') }}">Einloggen</a>
{% endif %}
Sie können es so machen.
Wenn Sie versuchen, auf einen Speicherort zuzugreifen, für den eine Anmeldung erforderlich ist, ohne sich anzumelden, können Sie ihn einschränken, solange "@ login_required" geschrieben ist. Sie können jedoch auf einen Speicherort zugreifen, für den während der Anmeldung keine Anmeldung erforderlich ist. Wenn dies möglich ist, befinden Sie sich in einer unsicheren Situation, in der Sie sich erneut anmelden können, obwohl Sie angemeldet sind. In einem solchen Fall
render_template('home.html')
nicht
return redirect(url_for('somewhere')) if current_user.is_authenticated else render_template('home.html')
Sie können es so machen.
Nachdem Sie eine neue Tabelle definiert haben, müssen Sie sie aktualisieren, damit sie wirksam wird.
---------------------------------------
MACOS/Linux
$ export FLASK_APP=main.py
Windows
$ set FLASK_APP=main.py
flask db init
#Nur der erste bisher
----------------------------------------
flask db migrate -m "message"
flask db upgrade
Sie können es so machen.
python main.py
Ich habe den Code, den ich bisher geschrieben habe, zusammengefasst, der wiederverwendet werden kann. Wenn Sie eine bessere Möglichkeit haben, es zu schreiben, lassen Sie es uns bitte wissen.