6- Flask 构建微电影视频网站-博客小项目学完flask基础

首先得感谢一下各位支持的朋友,因为你们的支持鼓励,自己才得以坚持利用时间分享一些小知识。非常感谢,因为你们让我少玩了王者农药,把时间用来做一些有意义的事情。

在本小节中,我们将一起学习JFinal的模板引擎的相关知识,因为内容比较多,所以我会分为几个小节讲解,当然也会有重点的讲解,忽略的地方还请各位道友自行查看文档。

默认情况下,Flask 在程序文件夹中的 templates
子文件夹中寻找模板。在下一个 hello.py 版本中,要把前面定义的模板保存在
templates 文件夹中,并分别命名为 index.html 和 user.html。

实战小项目介绍

  1. 项目介绍
  2. 项目演示
  3. 开发思路

实现用户注册,用户登录,退出登录,添加文章
文章分页列表,修改文章,删除文章等功能

开发思路:

图片 1

mark

一、本节摧毁目标

本节的目标主要是1、学会使用includedefine指令的使用;2、学会模板函数的调用。结合Db +
Record
进行数据操作,实现一个添加操作。

今天演示使用的依然是一个用户登录页面,知识稍微做了一些美化。我们在登录的时候去填写用户信息,然后点击登录按钮保存用户信息,因为节约时间就不直接在数据中添加数据。

index.thm的代码如下,不传参数

创建路由,视图,模板,静态文件

路由(route):

@app.route("/login/", methods=["GET","POST"]) # 用户登录
@app.route("/logout/", methods=["GET"]) # 用户退出
@app.route("/register/", methods=["GET","POST"]) # 用户注册
@app.route("/art/add", methods=["GET","POST"]) # 发布文章
@app.route("/art/edit/<int:id>/", methods=["GET","POST"]) # 编辑文章
@app.route("/art/list/", methods=["GET"]) # 文章列表
@app.route("/art/del/<int:id>/", methods=["GET"]) # 删除文章

路由就是我们访问网站时需要在浏览器中输入的一串地址。

视图(views):

login # 用户登录
logout # 用户退出
register # 用户注册
art_add # 发布文章
art_edit # 编辑文章
art_list # 文章列表
art_del # 删除文章

通过后端与前端的结合,通过视图书写一些后端的逻辑。

模板(templates):

login.html # 用户登录
register.html # 用户注册
art_add.html # 发布文章
art_edit.html # 编辑文章
art_list.html # 文章列表

html展示页面

静态文件(static):

css # 层叠样式表
js # javascript脚本
ue # 百度ueditor富文本编辑器

为项目创建自己的虚拟环境

mkvirtualenv -p=D:softEnvDownAnaconda2envspy36python.exe flaskgetstarted
pip install flask

创建一个纯python项目,选择我们刚才的虚拟环境。

图片 2

mark

将项目创建为如上图所示。

views.py:

# encoding: utf-8
__author__ = 'mtianyan'
__date__ = '2018/2/12 0012 00:34'

from flask import  Flask

app = Flask(__name__)

# login # 用户登录
# logout # 用户退出
# register # 用户注册
# art_add # 发布文章
# art_edit # 编辑文章
# art_list # 文章列表
# art_del # 删除文章

下面我们开始定义这些视图

# encoding: utf-8
__author__ = 'mtianyan'
__date__ = '2018/2/12 0012 00:34'

from flask import Flask, render_template, redirect, url_for

app = Flask(__name__)


# login 用户登录
@app.route("/login/", methods=["GET", "POST"])  # 用户登录
def login():
    # 返回渲染模板
    return render_template("login.html")


# logout 用户退出(302跳转到登录页面)
@app.route("/logout/", methods=["GET"])  # 用户退出
def logout():
    # 重定向到指定的视图对应url,蓝图中才可以使用
    # return redirect(url_for("app.login"))

    # 直接跳转路径
    return  redirect("/login/")


# register 用户注册
@app.route("/register/", methods=["GET", "POST"])  # 用户注册
def register():
    return render_template("register.html")


# art_add 发布文章
@app.route("/art/add/", methods=["GET", "POST"])  # 发布文章
def art_add():
    return render_template("art_add.html")


# art_edit 编辑文章
# 传入整型id参数
@app.route("/art/edit/<int:id>/", methods=["GET", "POST"])  # 编辑文章
def art_edit(id):
    return render_template("art_edit.html")


# art_list 文章列表
@app.route("/art/list/", methods=["GET"])  # 文章列表
def art_list():
    return render_template("art_list.html")


# art_del 删除文章
@app.route("/art/del/<int:id>/", methods=["GET"]) # 删除文章
def art_del(id):
    return redirect("/art/list")


if __name__ == "__main__":
    app.run(debug=True, host="127.0.0.1", port=8080)

可能遇到的访问错误:

builtins.TypeError
TypeError: art_del() got an unexpected keyword argument 'id'

你的方法没有将url中的参数接收进来。

定义视图使用函数方法,定义路由使用装饰器方法。
render_template()redirect()302跳转

  • url中包含可变参数,并在视图函数中接收
  • 如何启动:name main app.run

图片 3

mark

二、所需材料

1、一个数据库实例,一张数据表,演示所用表名t_user;表结构如下:

SET FOREIGN_KEY_CHECKS=0;-- ------------------------------ Table structure for t_user-- ----------------------------DROP TABLE IF EXISTS `t_user`;CREATE TABLE `t_user` ( `id` int NOT NULL AUTO_INCREMENT COMMENT '主键id', `email` varchar NOT NULL DEFAULT '' COMMENT '邮箱', `pwd` varchar NOT NULL COMMENT '密码', PRIMARY KEY  ENGINE=InnoDB AUTO_INCREMENT=5 DEFAULT CHARSET=utf8;

2、JFinal3.0相关的jar包和手册;3、网络(因为html页面使用了一些CDN服务);

<html>
    <head>
        <title>欢迎来到王者荣耀</title> 
    </head>
    <body>
        <p>你是不是要成为一个高手</p>
    </body>

</html>

Jinja2模板语法

  1. 继承

{% extends "父模板路径" %}
  1. 数据块(页面块)

{% block 块名 %} ... {% endblock %}
  1. 路由生成

{{ url_for("模块名.视图名") }}
  1. 静态文件加载

静态文件目录

{{ url_for('static', filename='静态文件路径')}}
  1. 循环语句:

{% for 条件 %} ... {% endfor %}
  1. 条件语句

显示什么不显示什么

{% if 条件 %} ... {% endif %}

三、写点html页面

下图就是要实现的页面效果,接下来我们将一起使用模板引擎玩一遍。这个页面分为2个组件部分,第一部分是系统名称部分,这部分使用#define指令完成;第二部分是数据表单部分,我们将表单存放在单独的页面,然后使用#include指令引入页面。敲黑板,╭╮本次使用的模板引擎不是freemarker,所以请你不要好心去设置viewType,本节演示所用的是JFinal提供的模板引擎。

图片 4就是这么棒

1、定义登录也top区域,这样定义的好处是,如果有多个地方需要使用到这样一个top区域的内容,我们不需要粘贴复制,只要通过一个调用指令就能完成;其次是便于维护,如果需求变更了,不需要一个个的去修改页面内容,只要修改一处就搞定。这样的场景能够理解吧?先创建一个html文件,命名为_login.html,然后编写如下代码,复制也行。

<!--使用#define 定义login函数-->#define login()<div ><h2>欢迎登录M9星球车辆信息管理系统 1.0</h2></div><!--#end结束定义-->#end

2、编写login_form.html页面

真的只是html页面内容。

<!--form表单,action指定到userLogin--><form action="/login/userLogin"> <!--email--> <div > <label for="inputEmail3" >Email</label> <div > <input type="email" placeholder="Email" name="email"> </div> </div> <!--账户密码--> <div > <label for="inputPassword3" >Password</label> <div > <input type="password" placeholder="Password" name="password"> </div> </div> <!--登录按钮--> <div > <div > <button type="submit" >登录</button> </div> </div> </form>

3、组装login.html页面

看起来很好玩OO哈哈~

<!--调用模板函数login-->#@login()<!DOCTYPE html><html lang="zh-CN"><head> <meta charset="utf-8"> <meta http-equiv="X-UA-Compatible" content="IE=edge"> <meta name="viewport" content="width=device-width, initial-scale=1"> <!-- 上述3个meta标签*必须*放在最前面,任何其他内容都*必须*跟随其后! --> <title>登录页面</title> <!-- Bootstrap --> <link href="http://apps.bdimg.com/libs/bootstrap/3.3.4/css/bootstrap.css" rel="stylesheet"> <!--引入login.css文件--> <link href="../css/login.css" rel="stylesheet"> <!-- HTML5 shim and Respond.js for IE8 support of HTML5 elements and media queries --> <!-- WARNING: Respond.js doesn't work if you view the page via file:// --> <!--[if lt IE 9]> <script src="https://cdn.bootcss.com/html5shiv/3.7.3/html5shiv.min.js"></script> <script src="https://cdn.bootcss.com/respond.js/1.4.2/respond.min.js"></script> <![endif]--></head><body><!--引入form表单页面-->#include("login_form.html")<!-- jQuery (necessary for Bootstrap's JavaScript plugins) --><script src="https://cdn.bootcss.com/jquery/1.12.4/jquery.min.js"></script></body></html>

user.html中传递一个参数

编写用户注册登录界面(Bootstrap)

Bootstrap

快速入门。

https://getbootstrap.com/docs/4.0/getting-started/download/

https://github.com/wangfupeng1988/wangEditor/releases

下载富文本编辑器将其中的release拷贝进目录并改名字

图片 5

mark

图片 6

mark

<!doctype html>
<html lang="zh-cn">
<head>
    <meta charset="UTF-8">
    <meta name="viewport"
          content="width=device-width, user-scalable=no, initial-scale=1.0, maximum-scale=1.0, minimum-scale=1.0">
    <meta http-equiv="X-UA-Compatible" content="ie=edge">
    <title>登录页面</title>
</head>
<body>

</body>
</html>

自己补全doctype html zh-cn

自行下载jquery.slim.min.js
自行下载 popper.min.js

百度在各自官网即可下载

<link rel="stylesheet" type="text/css" href="{{%20url_for('static',filename='css/bootstrap.min.css')%20}}">


<script src="{{%20url_for('static',filename='js/jquery-3.3.1.slim.min.js')%20}}"></script>
<script src="{{%20url_for('static',filename='js/popper.min.js')%20}}"></script>
<script src="{{%20url_for('static',filename='js/bootstrap.min.js')%20}}"></script>

注意后面三个js的加载顺序。以及css(head中) js(body中)

<div class="container" style="margin-top: 100px">
    <div class="row">
        <div class="col-md-12">
            <h3 class="text-center">文章管理系统</h3>
        </div>
    </div>
</div>

定义容器,内含行,定义栅格系统占12个位置。
h3标签使之变大,text-center居中,style margintop 距离上面100px

        <div class="col-md-6 offset-md-3">
            <div class="card-header">登录</div>
            <div class="card-body">
                <form>
                    <div class="form-group">
                        <label>账号</label>
                        <input type="text" class="form-control" placeholder="请输入账号">
                    </div>
                    <div class="form-group">
                        <label>密码</label>
                        <input type="password" class="form-control" placeholder="请输入密码">
                    </div>
                </form>
            </div>
        </div>

使用6个栅栏位置,并使用(12-6)/2进行居中操作。

  • 使用card-header card-body定义卡片头与内容
  • form group 中包含 label 和 input

定义登录

<a href="/register/">没有账号?前往注册</a>
<br>
 <a class="btn btn-primary" href="/art/list">登录</a>

新建user_base.html

将除了表单的都拷过来

图片 7

mark

把 login中的除form删除掉

图片 8

mark

此时访问登录的字不见了。因为title没有值传递过来。

return render_template("login.html", title ="登录")

四、编写LoginController并配置路由

1、编写登录控制器,假装就是真实的登录,虽然这里是添加数据,⁄(⁄ ⁄•⁄ω⁄•⁄
⁄)⁄

package com.demo.login;import com.jfinal.core.Controller;import com.jfinal.plugin.activerecord.Db;import com.jfinal.plugin.activerecord.Record;public class LoginController extends Controller { //默认方法 public void index() { render("login.html"); } /** * @author sugarYe * @date 2017/05/10 * @desc 用户登录 */ public void userLogin() { // 获取登录参数 String email = getPara; String password = getPara("password"); // 封装数据对象 Record user = new Record().set("email", email).set("pwd", password); // 持久化数据并接收处理状态 Boolean result = Db.save("t_user", user); // 判断执行结果 if  { // 处理你自己的业务 render("erro.html"); //自己随意编写这个页面 } //跳转到清单页面,这个页面请先自行编写 render("userList.html"); }}

2、配置路由

 /** * 配置路由 */ public void configRoute(Routes me) { me.add("/login",LoginController.class,"/login"); }
<html>
    <head>
        <title>欢迎来到王者荣耀</title> 
    </head>
    <body>
        <p>你是不是要成为一个高手,你的名字是{{name}}</p>
    </body>

</html>

注册页面

图片 9

mark

注册我们要引入自定义的js。

所以在base中在定义一个数据块,然后复写它。

图片 10

mark

http://www.bootcdn.cn/holder/

<script src="https://cdn.bootcss.com/holder/2.9.4/holder.min.js"></script>

引入holder.min.js图片占位。

传递注册title

<form>
                    <div class="form-group">
                        <label>账号</label>
                        <input type="text" class="form-control" placeholder="请输入账号">
                    </div>
                    <div class="form-group">
                        <label>密码</label>
                        <input type="password" class="form-control" placeholder="请输入密码">
                    </div>
                    <div class="form-group">
                        <label>确认密码</label>
                        <input type="password" class="form-control" placeholder="请确认密码">
                    </div>
                    <div class="form-group">
                        <label>验证码</label>
                        <input type="text" class="form-control" placeholder="请输入验证码">
                        <img data-src="holder.js/180x50" style="margin-top: 6px">
                    </div>
                    <a href="/login/">已有账号!前往登录</a>
                    <br>
                    <a class="btn btn-primary" href="/login/">注册</a></form>

五、配置共享函数模板

使用addSharedFunction即可配置共享的模板函数信息,此处接收的参数是字符串类型的路径信息。也就是你编写的模板函数的页面地址。

 /** * 配置模板信息 */ public void configEngine(Engine me) { me.addSharedFunction("/common/_login.html"); }

恭喜你,你已经完成了第一小节的所有的修炼,接下来就可以测试编写的成果了。加油!

在hello.py中,

编写文章编辑列表页面(百度ueditor)

头部和菜单是公共的部分:

<!doctype html>
<html lang="zh-cn">
<head>
    <meta charset="UTF-8">
    <meta name="viewport"
          content="width=device-width, user-scalable=no, initial-scale=1.0, maximum-scale=1.0, minimum-scale=1.0">
    <meta http-equiv="X-UA-Compatible" content="ie=edge">
    <title>文章管理系统</title>
    <link rel="stylesheet" type="text/css" href="{{%20url_for('static',filename='css/bootstrap.min.css')%20}}">

{% block css %} {% endblock %}

</head>
<body>

{% block js %} {% endblock %}
<script src="{{%20url_for('static',filename='js/jquery-3.3.1.slim.min.js')%20}}"></script>
<script src="{{%20url_for('static',filename='js/popper.min.js')%20}}"></script>
<script src="{{%20url_for('static',filename='js/bootstrap.min.js')%20}}"></script>
<script src="https://cdn.bootcss.com/holder/2.9.4/holder.min.js"></script>
</body>
</html>

首先将文件都引入。

六、函数使用回顾

使用define
指令,可以在jfinal中定义模板函数。使用时以#define 函数名()开始,如#define login();以#end结束。

include 指令用于将外部模板内容包含进来,
被包含的内容会被解析成为当前模板中的一部分进行使用。

PS:故事还长,请别失望。模板只是刚开始(__) 嘻嘻……

from flask import render_template
@app.route('/')
def index():
    return render_template('index.html')
@app.route('/user/<name>') #尖括号中的动态名字
def user(name):
    return render_template('user.html',name=name)

定义导航。

使用bootstrap的nav标签

图片 11

mark

<nav class="navbar navbar-light" style="background-color: #062c33">
    <div class="container">
        <a class="navbar-brand" style="color: #ffffff"> 文章管理系统</a>
        <a class="btn btn-outline-warning" href="/login/">账号名称 -> 退出</a>
    </div>
</nav>

定义左侧菜单:

<div class="container" style="margin-top: 6px">
    <div class="row">
        <div class="col-md-3">
            <div class="list-group">
                <a href="/art/add/" class="list-group-item list-group-item-action">发布文章</a>
                <a href="/art/list/" class="list-group-item list-group-item-action">文章列表</a>
            </div>
        </div>
        <div class="col-md-9"></div>
    </div>
</div>

其中左侧菜单占3个栅栏,剩下的9个归文章所有。

        <div class="col-md-9">
            <div class="card">
                <div class="card-header">文章列表</div>
                 <div class="card-body">
                     <table class="table table-bordered">
                         <thead>
                         <tr>
                             <th>标题</th>
                             <th>分类</th>
                             <th>封面</th>
                             <th>作者</th>
                             <th>发布时间</th>
                             <th>管理操作</th>
                         </tr>
                         </thead>
                         {% for v in range(1,11) %}
                     <tr>
                         <td>mtianyan编程之旅</td>
                         <td>python</td>
                         <td><img data-src="holder.js/75x40"></td>
                         <td>mtianyan</td>
                         <td>2018-02-12 12:00:00</td>
                         <td>
                             <button class="btn btn-sm btn-outline-success">编辑</button>
                             <button class="btn btn-sm btn-outline-danger">删除</button>
                         </td>
                     </tr>
                     {% endfor %}
                     </table>
                 </div>
            </div>
        </div>

成型效果:

图片 12

mark

分页:

 <nav>
                         <ul class="pagination">
                             <li class="page-item"><a class="page-link" href="#">上一页</a></li>
                             <li class="page-item"><a class="page-link" href="#">1</a></li>
                             <li class="page-item"><a class="page-link" href="#">2</a></li>
                             <li class="page-item"><a class="page-link" href="#">3</a></li>
                             <li class="page-item"><a class="page-link" href="#">4</a></li>
                             <li class="page-item"><a class="page-link" href="#">下一页</a></li>
                         </ul>
                     </nav>

图片 13

mark

创建art_base页面作为爸爸页面

将刚才的art_list页面内容全部拷贝。然后把可变部分9栏删除。用block
content代替

图片 14

mark

原本list文件中只保留可变部分9栏,继承art_base

图片 15

mark

图片 16

mark

可以看到如上图内容没有居中显示。我们可以右键检查打开查看元素

.table td,
.table th {
    padding: .75rem;
    vertical-align: top;
    border-top: 1px solid #dee2e6;
}

改为垂直居中

    .table td,
    .table th{
        vertical-align: middle;
    }

list中重写css block

图片 17

mark

1、变量

在模板中使用的 {{ name }}
结构表示一个变量,它是一种特殊的占位符,告诉模
板引擎这个位置的值从渲染模板时使用的数据中获取。
Jinja2
能识别所有类型的变量,甚至是一些复杂的类型,例如列表、字典和对象。在模板
中使用变量的一些示例如下:

     <p>A value from a dictionary: {{ mydict['key'] }}.</p>
     <p>A value from a list: {{ mylist[3] }}.</p>
     <p>A value from a list, with a variable index: {{ mylist[myintvar] }}.</p>
     <p>A value from an object's method: {{ myobj.somemethod() }}.</p>

可以使用过滤器修改变量,过滤器名添加在变量名之后,中间使用竖线分隔。例如,下述
模板以首字母大写形式显示变量 name 的值:

Hello, {{ name|capitalize }}

下面是常用的过滤器

图片 18

8568F68D-6315-4E2D-88A3-205D6C011941.png

更多的fliter官方文档

发布文章

  • 首先继承art_base

图片 19

mark

菜单分离出来使用include引入。

图片 20

mark

图片 21

mark

  • 实现active

添加block js代码

<script>
    $(document).ready(function () {
        $("#m2").addClass("active");
    });
</script>

列表页为m2 添加页为m1

可能遇到的不生效的错误

document是使用jQuery实现的,所以我们的blockjs一定要在jQuery引入之后

图片 22

mark

views中传入标题:

def art_list():
    return render_template("art_list.html",title="文章列表")

art_add 同理可得

然后在art_list和art_add中使用参数。

图片 23

mark

开始编写art_add 的content

<form>
    <div class="form-group">
        <label>标题</label>
        <input type="text" class="form-control" placeholder="请输入标题!">
    </div>
    <div class="form-group">
        <label>分类</label>
        <select class="form-control">
            <option value="1">科技</option>
            <option value="2">搞笑</option>
            <option value="3">军事</option>
        </select>
    </div>
    <div class="form-group">
        <label>封面</label>
        <input type="file" class="form-control-file"style="margin-left: 2px;">
        <img data-src="holder.js/300x160" style="margin-top: 6px;">
        <a class="btn btn-primary" style="margin-top: 6px;">上传封面</a>
    </div>
    <div class="form-group">
         <label>内容</label>
        <textarea class="form-control"></textarea>
    </div>
</form>

此时我们的内容还并不是那个富文本,因此我们这时候需要将富文本集成。

前往官网下载php版本拷入项目目录

图片 24

mark

加载ue需要的js

图片 25

mark

给我们的内容一个id=content

    <div class="form-group">
         <label>内容</label>
        <textarea class="form-control" id="content"></textarea>
    </div>

然后在js中

    var ue = UE.getEditor("content");

将原来的textera的class去掉。修复样式

    <div class="form-group">
         <label>内容</label>
        <textarea id="content" style="height: 300px;"></textarea>
    </div>
    <button type="button" class="btn btn-primary">发布文章</button>

2、Jinja2的控制结构

if – else 的写法

    {% if name %}
        Hello,{{name}}
    {% else %}
        Hello ,你没名字一看就是菜啊!!!
    {% endif %}

for 循环

    {% for title in ["黄金4","黄金3","黄金2"] %}
        <li>{{title}}</li>
    {% endfor %}

Jinja2 还支持宏。宏类似于 Python 代码中的函数。例如:

{% macro render_comment(comment) %} 
       <li>{{ comment }}</li>
{% endmacro %}
<ul>
      {% for comment in comments %}
      {{ render_comment(comment) }} 
      {% endfor %}
</ul>

为了重复使用宏,我们可以将其保存在单独的文件中,然后在需要使用的模板中导入:

{% import 'macros.html' as macros %}
 <ul>
    {% for comment in comments %}
    {{ macros.render_comment(comment) }}
    {% endfor %} 
</ul>

需要在多处重复使用的模板代码片段可以写入单独的文件,再包含在所有模板中,以避免
重复:

{% include 'common.html' %}

另一种重复使用代码的强大方式是模板继承,它类似于 Python
代码中的类继承。首先,创
建一个名为 base.html 的基模板:

<html>
    <head>
        {% block head %}
        <title>{% block title %}{% endblock %} - MyApplication</title>
        {% endblock %}
    </head>
    <body>
        {%block body %}
        <p>我是来自基类</p>
        {%endblock %}
    </body>

</html>

新建一个son.html 继承base.html

{% extends "base.html" %}
{% block title %} INDEX {% endblock %}
{% block head %}
    {{super()}}
{% endblock %}
{% block body %}
{{super()}}
<h1>我也是醉了,这是啥基础自基础模板</h1>
{% endblock %}

extends 指令声明这个模板衍生自 base.html。在 extends
指令之后,基模板中的 3 个块被
重新定义,模板引擎会将其插入适当的位置。注意新定义的 head
块,在基模板中其内容不 是空的,所以使用 super() 获取原来的内容。

使用sqlalchemy定义数据表

操作mysql

ssh root@192.168.0.7
mysql -uroot -p
s

图片 26

mark

可以看到当前的状态。

vim /etc/my.cnf

图片 27

mark

图片 28

mark

修改mysql编码。

图片 29

mark

然后重启服务service mysql restart。再次查看。

图片 30

mark

四个utf8表示设置成功。

centos: 编辑vim /ect/my.cnf

创建数据库 artcms

原生方法与model ORM方式对比

创建artcms.sql并思考我们需要的字段

/*
用户表
0. id编号
1. 账号
2. 密码
3. 注册时间
 */

CREATE TABLE if NOT EXISTS user(
  id int unsigned not null auto_increment key comment "主键ID",
  account varchar(20) not null comment "账号",
  pwd  varchar(100) not null comment "密码",
  addtime datetime not null comment "注册时间"
)engine=InnoDB DEFAULT charset=utf8 comment "用户";

/*
文章表
0. id编号
1. 标题
2. 分类
3. 作者
4. 封面
5. 内容
6. 发布时间
 */
CREATE TABLE if NOT EXISTS article(
  id int unsigned not null auto_increment key comment "主键ID",
  title varchar(100) not null comment "标题",
  category  tinyint unsigned not null comment "分类",
  user_id int unsigned not null comment "作者",
  logo varchar(100) not null comment "封面",
  content mediumtext not null comment "文章",
  addtime datetime not null comment "发表时间"
)engine=InnoDB DEFAULT charset=utf8 comment "文章";

操作数据库需要使用原生语句。以后不用mysql 数据库迁移存在问题。

安装mysql client

lsof -i:3306
pip install Flask-SQLAlchemy

# encoding: utf-8
__author__ = 'mtianyan'
__date__ = '2018/2/12 0012 00:35'
from flask import Flask
from flask_sqlalchemy import SQLAlchemy

app = Flask(__name__)
app.config["SQLALCHEMY_DATABASE_URI"] = "mysql://root:tp158917@127.0.0.1:3306/artcms"
# 如果设置成 True (默认情况),Flask-SQLAlchemy 将会追踪对象的修改并且发送信号。
app.config["SQLALCHEMY_TRACK_MODIFICATIONS"] = True

# 绑定app至SQLAlchemy
db = SQLAlchemy(app)

"""
用户模型
0. id编号
1. 账号
2. 密码
3. 注册时间
"""


class User(db.Model):
    __tablename__ = "user"
    id = db.Column(db.Integer, primary_key=True)  # 编号id
    account = db.Column(db.String(20), nullable=False)  # 账号非空
    pwd = db.Column(db.String(100), nullable=False)  # 密码非空
    add_time = db.Column(db.DateTime, nullable=False)  # 注册时间

    # 查询时的返回
    def __repr__(self):
        return "<User %r>" % self.account


"""
文章模型
0. id编号
1. 标题
2. 分类
3. 作者
4. 封面
5. 内容
6. 发布时间
"""


class Article(db.Model):
    __tablename__ = "article"
    id = db.Column(db.Integer, primary_key=True)  # 编号id
    title = db.Column(db.String(100), nullable=False)  # 标题非空
    category = db.Column(db.Integer, nullable=False)  # 编号id
    user_id = db.Column(db.Integer, nullable=False)  # 作者
    logo = db.Column(db.String(100), nullable=False)  # 封面
    content = db.Column(db.Text, nullable=False)  # 内容
    add_time = db.Column(db.DateTime, nullable=False)  # 发布时间

    # 查询时的返回
    def __repr__(self):
        return "<Article %r>" % self.title

# 执行创建表语句
if __name__ == "__main__":
    db.create_all()

执行时警告

 Warning: (1366, "Incorrect string value: '\xD6\xD0\xB9\xFA\xB1\xEA...' for column 'VARIABLE_VALUE' at row 480")

windows下暂无解决方案。把mysql所有编码都设为utf8也不行。连接一个linux下数据库没有该警告。

相关文章

发表评论

电子邮件地址不会被公开。 必填项已用*标注

*
*
Website