📅  最后修改于: 2023-12-03 15:17:45.289000             🧑  作者: Mango
在Web开发中,MVC模式被广泛应用于构建应用程序。MVC是Model-View-Controller的缩写,是一种将应用程序分解为三个核心组件:模型、视图和控制器的设计模式。每个组件负责处理特定的应用程序功能:
MVC框架提供了一种结构良好、可扩展、易于维护的方式来组织和管理Web应用程序。在本文中,我们将介绍一个高级示例,展示如何使用MVC框架构建一个功能完整的Web应用程序。
在本示例中,我们将使用一下技术栈:
我们将使用以下设计模式来构建示例Web应用程序:
我们的应用程序将包含以下基本组件:
应用程序的完整结构如下所示:
app/
static/
css/
style.css
js/
app.js
templates/
base.html
home.html
login.html
register.html
__init__.py
config.py
factory.py
controller.py
model/
__init__.py
user.py
service/
__init__.py
user_service.py
auth_service.py
repository/
__init__.py
user_repository.py
auth_repository.py
utils/
__init__.py
decorators.py
我们的应用程序将有两个数据模型:User和Auth。User模型将负责管理应用程序的用户数据,而Auth模型将负责管理用户的身份验证信息。
# app/model/user.py
from app import db
class User(db.Model):
__tablename__ = 'users'
id = db.Column(db.Integer, primary_key=True)
username = db.Column(db.String(80), nullable=False)
email = db.Column(db.String(120), unique=True, nullable=False)
password = db.Column(db.String(80), nullable=False)
def __repr__(self):
return f'<User {self.username}>'
# app/model/auth.py
from app import db
class Auth(db.Model):
__tablename__ = 'auth'
id = db.Column(db.Integer, primary_key=True)
user_id = db.Column(db.Integer, db.ForeignKey('users.id'), nullable=False)
token = db.Column(db.String(80), nullable=False)
def __repr__(self):
return f'<Auth {self.token}>'
我们的应用程序将有四个视图:Home、Login、Register和Logout。
<!-- app/templates/base.html -->
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1">
<title>{% block title %}Untitled{% endblock %}</title>
<link href="{{ url_for('static', filename='css/style.css') }}" rel="stylesheet">
</head>
<body>
<nav>
<ul>
<li><a href="{{ url_for('home') }}">Home</a></li>
{% if current_user %}
<li><a href="{{ url_for('logout') }}">Logout</a></li>
{% else %}
<li><a href="{{ url_for('login') }}">Login</a></li>
<li><a href="{{ url_for('register') }}">Register</a></li>
{% endif %}
</ul>
</nav>
<main>
{% block content %}{% endblock %}
</main>
<script src="{{ url_for('static', filename='js/app.js') }}"></script>
</body>
</html>
<!-- app/templates/home.html -->
{% extends 'base.html' %}
{% block title %}Home{% endblock %}
{% block content %}
<h1>Welcome to our application!</h1>
{% endblock %}
<!-- app/templates/login.html -->
{% extends 'base.html' %}
{% block title %}Login{% endblock %}
{% block content %}
{% if error %}
<div class="alert">{{ error }}</div>
{% endif %}
<form action="{{ url_for('login') }}" method="POST">
<label>Username</label>
<input type="text" name="username" required>
<label>Password</label>
<input type="password" name="password" required>
<input type="submit" value="Login">
</form>
{% endblock %}
<!-- app/templates/register.html -->
{% extends 'base.html' %}
{% block title %}Register{% endblock %}
{% block content %}
{% if error %}
<div class="alert">{{ error }}</div>
{% endif %}
<form action="{{ url_for('register') }}" method="POST">
<label>Username</label>
<input type="text" name="username" required>
<label>Email</label>
<input type="email" name="email" required>
<label>Password</label>
<input type="password" name="password" required>
<input type="submit" value="Register">
</form>
{% endblock %}
我们的应用程序将有四个路由:/、/login、/register和/logout。控制器将负责处理这些路由,并调用相应的模型和视图方法。
# app/controller.py
from flask import Blueprint, render_template, request, redirect, url_for, session
from app.factory import create_app
from app.service.user_service import UserService
from app.service.auth_service import AuthService
bp = Blueprint('site', __name__)
@bp.route('/')
def home():
return render_template('home.html')
@bp.route('/login', methods=['GET', 'POST'])
def login():
if request.method == 'POST':
username = request.form['username']
password = request.form['password']
user = UserService().authenticate(username, password)
if user is None:
return render_template('login.html', error='Invalid username or password')
session['user_id'] = user.id
return redirect(url_for('site.home'))
return render_template('login.html')
@bp.route('/register', methods=['GET', 'POST'])
def register():
if request.method == 'POST':
username = request.form['username']
email = request.form['email']
password = request.form['password']
user_service = UserService()
user = user_service.create(username=username, email=email, password=password)
if user is None:
return render_template('register.html', error='Unable to register user')
auth_service = AuthService()
auth_token = auth_service.create_token(user.id)
session['user_id'] = user.id
return redirect(url_for('site.home'))
return render_template('register.html')
@bp.route('/logout')
def logout():
session.pop('user_id', None)
return redirect(url_for('site.home'))
我们将使用工厂模式来创建和管理应用程序的核心组件。我们的工厂将注册所有视图、控制器和数据模型,并返回一个Flask程序实例。
# app/factory.py
from flask import Flask
from app.config import Config
from app.model import User, Auth
from app.controller import bp
from app.repository import UserRepository, AuthRepository
from app.service import UserService, AuthService
from app.utils.decorators import requires_auth
def create_app(config=Config):
app = Flask(__name__)
app.config.from_object(config)
# Register controllers
app.register_blueprint(bp)
# Register data models
db.init_app(app)
with app.app_context():
db.create_all()
# Register repositories
user_repository = UserRepository(User)
auth_repository = AuthRepository(Auth)
# Register services
user_service = UserService(user_repository)
auth_service = AuthService(user_repository, auth_repository)
# Register decorators
app.before_request(requires_auth)
return app
我们将使用依赖注入容器来解耦和管理组件之间的依赖关系。我们的容器将提供一个register方法,用于向容器注册新组件,以及get方法,用于检索已注册的组件。在本示例中,我们将使用简单的字典作为我们的容器。
# app/utils/container.py
class Container:
def __init__(self):
self._registry = {}
def register(self, key, value):
self._registry[key] = value
def get(self, key):
return self._registry.get(key)
现在,我们可以启动应用程序并访问/路由来进入我们的Web应用程序。对于本示例,我们将执行以下命令:
export FLASK_APP=app
export FLASK_ENV=development
flask run
现在,我们可以在我们的浏览器中访问http://localhost:5000,并查看我们的应用程序。