目录
2、templates/article下新增 article_add.html
3、templates/article下新增 all.html
4、templates/article下新增 user_article.html
8、修改templates/user下center.html
最为常见的关系就是一对多的关系。因为关系在它们建立之前就已经声明,您可以使用 字符串来指代还没有创建的类(例如如果 Person 定义了一个到 Article 的关系,而 Article 在文件的后面才会声明)。
关系使用 relationship() 函数表示。然而外键必须用类 sqlalchemy.schema.ForeignKey 来单独声明:
class Person(db.Model): id = db.Column(db.Integer, primary_key=True) name = db.Column(db.String(50)) addresses = db.relationship('Address', backref='person', lazy='dynamic') class Address(db.Model): id = db.Column(db.Integer, primary_key=True) email = db.Column(db.String(50)) person_id = db.Column(db.Integer, db.ForeignKey('person.id'))
db.relationship()
做了什么?这个函数返回一个可以做许多事情的新属性。在本案例中,我们让它指向 Address 类并加载多个地址。它如何知道会返回不止一个地址?因为 SQLALchemy 从您的声明中猜测了一个有用的默认值。 如果您想要一对一关系,您可以把 uselist=False
传给 relationship() 。
那么 backref 和 lazy 意味着什么了?backref 是一个在 Address 类上声明新属性的简单方法。您也可以使用 my_address.person
来获取使用该地址(address)的人(person)。lazy 决定了 SQLAlchemy 什么时候从数据库中加载数据:
'select'
(默认值) 就是说 SQLAlchemy 会使用一个标准的 select 语句必要时一次加载数据。'joined'
告诉 SQLAlchemy 使用 JOIN 语句作为父级在同一查询中来加载关系。'subquery'
类似'joined'
,但是 SQLAlchemy 会使用子查询。'dynamic'
在有多条数据的时候是特别有用的。不是直接加载这些数据,SQLAlchemy 会返回一个查询对象,在加载数据前您可以过滤(提取)它们。
您如何为反向引用(backrefs)定义惰性(lazy)状态?使用 backref() 函数:
class User(db.Model): id = db.Column(db.Integer, primary_key=True) name = db.Column(db.String(50)) addresses = db.relationship('Address', backref=db.backref('person', lazy='joined'), lazy='dynamic')
一、目录结构
1、目录图
2、apps下__init__.py
from flask import Flask
import settings
from apps.user.view import user_bp
from ext import db
def create_app():
app = Flask(__name__, template_folder='../templates', static_folder='../static')
# 加载配置
app.config.from_object(settings.DevelopmentConfig)
# 将db对象与app进行关联
db.init_app(app=app)
# 蓝图 ,将蓝图对象绑定到app上
app.register_blueprint(user_bp)
return app
if __name__ == '__main__':
app = create_app()
app.run()
3、settings.py
#!/usr/bin/env python
# -*- coding: utf-8 -*-
# @Time : 2021/12/16 9:53
# @Author : niubobo
# @File : settings.py
# @Software: PyCharm
class Config:
DEBUG = True
# 数据库配置
SQLALCHEMY_DATABASE_URI = 'mysql+pymysql://用户:密码@ip:3306/blog'
SQLALCHEMY_TRACK_MODIFICATIONS = False
SQLALCHEMY_ECHO = True
class DevelopmentConfig(Config):
ENV = 'development'
class ProductionConfig(Config):
ENV = 'production'
DEBUG = False
4、app.py
from flask_script import Manager
from flask_migrate import Migrate, MigrateCommand
from apps import create_app
from ext import db
from apps.user.models import User
from apps.article.models import Article
app = create_app()
print(app)
manager = Manager(app=app)
# 命令工具
migrate = Migrate(app=app, db=db)
# 添加命令到manager
manager.add_command('db', MigrateCommand)
@manager.command
def init():
print('初始化')
if __name__ == '__main__':
manager.run()
二、模型创建
1、apps/user目录下 models.py
#!/usr/bin/env python
# -*- coding: utf-8 -*-
# @Time : 2021/12/16 10:01
# @Author : niubobo
# @File : models.py
# @Software: PyCharm
from datetime import datetime
from ext import db
class User(db.Model):
id = db.Column(db.Integer, primary_key=True, autoincrement=True)
username = db.Column(db.String(15), nullable=False)
password = db.Column(db.String(64), nullable=False)
phone = db.Column(db.String(11), unique=True, nullable=True)
email = db.Column(db.String(30))
icon = db.Column(db.String(100))
isdelete = db.Column(db.Boolean, default=False)
rdatetime = db.Column(db.DateTime, default=datetime.now)
# 增加一个字段
articles = db.relationship('Article', backref='user')
def __str__(self):
return self.username
2、apps/artice目录下 models.py
#!/usr/bin/env python
# -*- coding: utf-8 -*-
# @Time : 2021/12/17 13:14
# @Author : niubobo
# @File : models.py
# @Software: PyCharm
from datetime import datetime
from ext import db
class Article(db.Model):
id = db.Column(db.Integer, primary_key=True, autoincrement=True)
title = db.Column(db.String(50), nullable=False)
content = db.Column(db.Text, nullable=False)
pdatetime = db.Column(db.DateTime, default=datetime.now)
click_num = db.Column(db.Integer, default=0)
save_num = db.Column(db.Integer, default=0)
love_num = db.Column(db.Integer, default=0)
# 外键
user_id = db.Column(db.Integer, db.ForeignKey('user.id'), nullable=False)
3、生成模型库表
终端输入命令执行:
python app.py db init
python app.py db migrate
python app.py db upgrade
三、应用
稍微改造一下前面课程代码进行用户注册
实现以下:
1、templates下新增article文件夹
2、templates/article下新增 article_add.html
{% extends 'base.html' %}
{% block title %}
添加文章
{% endblock %}
{% block middle %}
<form action="{{ url_for('article.publish_article') }}" method="post">
<p><input type="text" name="title" placeholder="文章标题"></p>
<p>
<textarea cols="50" rows="10" name="content" placeholder="输入文章内容">
</textarea>
</p>
<p>
用户:
<select name="uid" >
<option value="0">请选择用户</option>
{% for user in users %}
<option value="{{ user.id }}">{{ user.username }}</option>
{% endfor %}
</select>
</p>
<p><input type="submit" value="添加文章"></p>
</form>
{% endblock %}
3、templates/article下新增 all.html
关键:
{% extends 'base.html' %}
{% block title %}
文章列表
{% endblock %}
{% block modle_style %}
<style>
#container{
border: 1px solid brown;
margin-bottom: 10px;
padding: 5px;
}
</style>
{% endblock %}
{% block middle %}
<div style="border: 10px seagreen; margin-right: 50px; padding: 5px; text-align: right;"><a href="{{ url_for('article.publish_article') }}">发表文章</a></div>
{% for article in articles %}
<div id="container">
<p>
<h3>{{ article.title }}</h3>
<div>作者:{{ article.user.username }}</div>
</p>
<p>{{ article.content }}</p>
<div>{{ article.pdatetime }}</div>
</div>
{% endfor %}
{% endblock %}
4、templates/article下新增 user_article.html
关键
{% extends 'base.html' %}
{% block title %}
用户文章列表
{% endblock %}
{% block modle_style %}
<style>
#container{
border: 1px solid brown;
margin-bottom: 10px;
padding: 5px;
}
</style>
{% endblock %}
{% block middle %}
{% for article in user.articles %}
<div id="container">
<p>
<h3>{{ article.title }}</h3>
<div>作者:{{ user.username }}</div>
</p>
<p>{{ article.content }}</p>
<div>{{ article.pdatetime }}</div>
</div>
{% endfor %}
{% endblock %}
5、apps/article下新增 view.py
#!/usr/bin/env python
# -*- coding: utf-8 -*-
# @Time : 2021/12/17 13:41
# @Author : niubobo
# @File : view.py.py
# @Software: PyCharm
from flask import Blueprint, request, render_template, redirect, url_for
from sqlalchemy import or_, and_
from apps.article.models import Article
from apps.user.models import User
from ext import db
article_bp = Blueprint('article', __name__)
@article_bp.route('/publish', methods=['GET', 'POST'])
def publish_article():
if request.method == 'POST':
title = request.form.get('title')
content = request.form.get('content')
uid = request.form.get('uid')
# 添加文章
article = Article()
article.title = title
article.content = content
article.user_id = uid
db.session.add(article)
db.session.commit()
return redirect(url_for('article.all_article'))
else:
users = User.query.filter(User.isdelete == False).all()
return render_template('article/article_add.html', users=users)
@article_bp.route('/all')
def all_article():
articles = Article.query.all()
return render_template('article/all.html', articles=articles)
@article_bp.route('/userArticle')
def user_article():
id = request.args.get('id')
user = User.query.get(id)
have_article = Article.query.filter(Article.user_id == id).first()
# 这个判断是我加得,该例子可以去掉
if have_article:
return render_template('article/user_article.html', user=user)
else:
return render_template('article/user_article.html', user=user, msg='该用户还未发表博文!')
6、修改apps下__init__.py
注册到蓝图
from flask import Flask
import settings
from apps.article.view import article_bp
from apps.user.view import user_bp
from ext import db
def create_app():
app = Flask(__name__, template_folder='../templates', static_folder='../static')
# 加载配置
app.config.from_object(settings.DevelopmentConfig)
# 将db对象与app进行关联
db.init_app(app=app)
# 蓝图 ,将蓝图对象绑定到app上
app.register_blueprint(user_bp)
app.register_blueprint(article_bp)
return app
if __name__ == '__main__':
app = create_app()
app.run()
7、修改base.html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>
{% block title %} 父模板的title{% endblock %}
</title>
<style>
#head{
height: 50px;
background-color: bisque;
}
#head ul{
list-style: none;
height: 50px;
}
#head ul li{
float: left;
width: 100px;
text-align: center;
font-size: 15px;
line-height: 50px;
}
#middle{
height: 100%;
background-color: azure;
}
#foot{
height: 50px;
line-height: 50px;
background-color: darkolivegreen;
}
</style>
{% block modle_style %}{% endblock %}
{% block jquery %}{% endblock %}
</head>
<body>
<div id="head">
<ul>
<li><a href="{{ url_for('user.user_center') }}">首页</a></li>
<li><a href="{{ url_for('user.register') }}">注册</a></li>
<li><a href="{{ url_for('user.login') }}">登录</a></li>
<li><a href="{{ url_for('article.all_article') }}">博客</a></li>
<li><a href="">会员</a></li>
</ul>
</div>
<div id="middle">
{% block middle %} 中间{% endblock %}
</div>
<div id="foot">
我是底部
</div>
{% block myjs %}{% endblock %}
</body>
</html>
8、修改templates/user下center.html
{% extends 'base.html' %}
{% block title %}
用户信息
{% endblock %}
{% block jquery %}
<script src="https://cdn.bootcdn.net/ajax/libs/jquery/3.1.0/jquery.min.js"></script>
{% endblock %}
{% block middle %}
<h2>所有用户信息如下:</h2>
搜索: <input type="text" name="search" placeholder="输入用户名或手机号码"> <input type="button" value="搜索" id="search">
<br>
{% if users %}
<span>当前用户人数:{{ users|length }}人</span>
<table border="1" cellspacing="0" width="70%">
<tr>
<th>序号</th>
<th>用户名</th>
<th>手机号</th>
<th>邮箱</th>
<th>注册时间</th>
<th>操作</th>
</tr>
{% for user in users %}
<tr>
<td>{{ loop.index }}</td>
<td>{{ user.username }}</td>
<td>{{ user.phone }}</td>
<td>{{ user.email }}</td>
<td>{{ user.rdatetime }}</td>
<td><a href={{ url_for('user.update_user') }}?id={{ user.id }}">修改</a>
<a href={{ url_for('user.del_user') }}?id={{ user.id }}">删除</a>
<a href={{ url_for('article.user_article') }}?id={{ user.id }}">博文</a></td>
<!-- <td><a href="javascript:;" onclick="update('{{ user.username }}')">修改</a>
<a href="javascript:;" onclick="del('{{ user.username }}')">删除</a></td> -->
</tr>
{% endfor %}
</table>
{% else %}
<p style="color: red; font-size: 20px;">当前还没有任何用户,抓紧时间注册吧!!</p>
{% endif %}
{% endblock %}
{% block myjs %}
<script>
//检索
$('#search').click(function () {
let content = $("input[name='search']").val();
location.href = '{{ url_for('user.search') }}?search='+content
// http://ip:端口/search?search=输入的值
})
//删除函数
// function del(username) {
// console.log(username)
// // location 地址栏对象
// location.href = '/del?username='+username
// }
//修改函数
// function update(username) {
// location.href = '/update?username='+username
// }
</script>
{% endblock %}