python-flask和mysql的web项目

最近学习python,本来计划今天写一下phthon的一些集合的运用包括函数的运用,但是在学习flask的时候,发现他的网站的东西有一些错误,导致初学者如果学习起来会出问题,尽管我也是一个初学者,但是我不希望接下来的人再继续出这个问题了,就把一个python搭建一个简单的web项目来搭建出来。

项目结构

看目录之前先下载一些框架,我是在python3.6的基础下安装的,如果你需要别的,自己百度一下吧。
pip install Flask
pip install flask-mysql
这个项目没有所谓的三层架构,就有一层,结果目录如下
项目结构
工具是pyCharm,新建一个项目-flask-mysqldb,文件目录如下:

flask-mysqldb
    examples
        static
        templates
    flask_mysqldb

连接数据库

假定你已经本地安装了mysql,那么直接就可以开始操作了,在flask_mysqldb下新建init.py文件,来连接数据库

import MySQLdb
from MySQLdb import cursors
from flask import _app_ctx_stack, current_app


class MySQL(object):

    def __init__(self, app=None):
        self.app = app
        if app is not None:
            self.init_app(app)

    def init_app(self, app):
        app.config.setdefault('MYSQL_HOST', 'localhost')
        app.config.setdefault('MYSQL_USER', 'root')
        app.config.setdefault('MYSQL_PASSWORD', '******')
        app.config.setdefault('MYSQL_DB', 't_app_info')
        app.config.setdefault('MYSQL_PORT', 3306)
        app.config.setdefault('MYSQL_UNIX_SOCKET', None)
        app.config.setdefault('MYSQL_CONNECT_TIMEOUT', 10)
        app.config.setdefault('MYSQL_READ_DEFAULT_FILE', None)
        app.config.setdefault('MYSQL_USE_UNICODE', True)
        app.config.setdefault('MYSQL_CHARSET', 'utf8')
        app.config.setdefault('MYSQL_SQL_MODE', None)
        app.config.setdefault('MYSQL_CURSORCLASS', None)
        app.config.setdefault('USERNAME','menghaibin')
        app.config.setdefault('PASSWORD','123')
        app.config['SECRET_KEY'] = 'nihao'

        if hasattr(app, 'teardown_appcontext'):
            app.teardown_appcontext(self.teardown)

    @property
    def connect(self):
        kwargs = {}

        if current_app.config['MYSQL_HOST']:
            kwargs['host'] = current_app.config['MYSQL_HOST']

        if current_app.config['MYSQL_USER']:
            kwargs['user'] = current_app.config['MYSQL_USER']

        if current_app.config['MYSQL_PASSWORD']:
            kwargs['passwd'] = current_app.config['MYSQL_PASSWORD']

        if current_app.config['MYSQL_DB']:
            kwargs['db'] = current_app.config['MYSQL_DB']

        if current_app.config['MYSQL_PORT']:
            kwargs['port'] = current_app.config['MYSQL_PORT']

        if current_app.config['MYSQL_UNIX_SOCKET']:
            kwargs['unix_socket'] = current_app.config['MYSQL_UNIX_SOCKET']

        if current_app.config['MYSQL_CONNECT_TIMEOUT']:
            kwargs['connect_timeout'] = \
                current_app.config['MYSQL_CONNECT_TIMEOUT']

        if current_app.config['MYSQL_READ_DEFAULT_FILE']:
            kwargs['read_default_file'] = \
                current_app.config['MYSQL_READ_DEFAULT_FILE']

        if current_app.config['MYSQL_USE_UNICODE']:
            kwargs['use_unicode'] = current_app.config['MYSQL_USE_UNICODE']

        if current_app.config['MYSQL_CHARSET']:
            kwargs['charset'] = current_app.config['MYSQL_CHARSET']

        if current_app.config['MYSQL_SQL_MODE']:
            kwargs['sql_mode'] = current_app.config['MYSQL_SQL_MODE']

        if current_app.config['MYSQL_CURSORCLASS']:
            kwargs['cursorclass'] = getattr(cursors, current_app.config['MYSQL_CURSORCLASS'])

        return MySQLdb.connect(**kwargs)

    @property
    def connection(self):


        ctx = _app_ctx_stack.top
        if ctx is not None:
            if not hasattr(ctx, 'mysql_db'):
                ctx.mysql_db = self.connect
            return ctx.mysql_db

    def teardown(self, exception):
        ctx = _app_ctx_stack.top
        if hasattr(ctx, 'mysql_db'):
            ctx.mysql_db.close()

设置config的值的时候,可以使用app.config[‘SECRET_KEY’] = ‘123’,也可以app.config.setdefault(‘PASSWORD’,’123’),这两种设置都可以的,连接数据库的配置就不多说了,各个配置代表什么,基本了解数据库的人也都懂,反正我们基本用到的无非就是一个地址,数据库,超时时间,编码格式这些。

业务逻辑

在examples文件夹下新建app.py,然后复制如下代码到文件中

from flask import Flask, request, session, redirect, url_for, abort, \
    render_template, flash

from flask_mysqldb import MySQL

app = Flask(__name__)
mysql = MySQL(app)

#获取数据库
def get_db():
    return mysql.connection.cursor()

#首页
@app.route('/show_entries')
def show_entries():

    cur = get_db()
    cur.execute('select title, text from entries order by id desc')
    entries = [dict(title=row[0], text=row[1]) for row in cur.fetchall()]
    return render_template('show_entries.html', entries=entries)


#登录页
@app.route('/login', methods=['GET', 'POST'])
def login():
    error = None
    if request.method == 'POST':
        if request.form['username'] != app.config['USERNAME']:
            error = 'Invalid username'
        elif request.form['password'] != app.config['PASSWORD']:
            error = 'Invalid password'
        else:
            session['logged_in'] = True
            flash('You were logged in')
            return redirect(url_for('show_entries'))
    return render_template('login.html', error=error)


#添加条目
@app.route('/add_entry', methods=['POST'])
def add_entry():
    cur = get_db()
    if not session.get('logged_in'):
        abort(401)

    title = str(request.form['title'])
    text = str(request.form['text'])
    print()
    cur.execute('insert into entries (title, text) values (%s, %s)',
                [title,text])
    mysql.connection.commit()
    flash('New entry was successfully posted')
    return redirect(url_for('show_entries'))

#退出登录
@app.route('/logout')
def logout():
    session.pop('logged_in', None)
    flash('You were logged out')
    return redirect(url_for('show_entries'))


if __name__ == '__main__':
    app.run(debug=True)

各个业务名称已经在文件中标明了,就不再说了,但是大家注意到了url_for这个方法,这个方法比较坑了
url_for()函数是用于构建指定函数的URL,也就是说他找的是函数,而不是route这个路由的路径,所以你一定要写函数名称,否则回报这个错误
werkzeug.routing.BuildError: Could not build url for endpoint ‘show_entries’. Did you mean ‘add_entry’ instead? 折腾了我一个小时,才发现在flask的官网他都没有管这个,结果一直报错

页面

登录页面

在templates文件夹中创建login.html.

{% extends "layout.html" %}
{% block body %}
  <h2>Login</h2>
  {% if error %}<p class=error><strong>Error:</strong> {{ error }}{% endif %}
  <form action="{{ url_for('login') }}" method=post>
    <dl>
      <dt>Username:
      <dd><input type=text name=username>
      <dt>Password:
      <dd><input type=password name=password>
      <dd><input type=submit value=Login>
    </dl>
  </form>
{% endblock %}

退出登录

在templates文件夹中添加logout.html

<!doctype html>
<title>Flaskr</title>
<link rel=stylesheet type=text/css href="{{ url_for('static', filename='style.css') }}">
<div class=page>
  <h1>Flaskr</h1>
  <div class=metanav>
  {% if not session.logged_in %}
    <a href="{{ url_for('login') }}">log in</a>
  {% else %}
    <a href="{{ url_for('logout') }}">log out</a>
  {% endif %}
  </div>
  {% for message in get_flashed_messages() %}
    <div class=flash>{{ message }}</div>
  {% endfor %}
  {% block body %}{% endblock %}
</div>

首页

在templates文件夹中创建show_entries.html文件

{% extends "layout.html" %}
{% block body %}

  {% if session.logged_in %}
    <form action="{{ url_for('add_entry') }}" method=post class=show_entries>
      <dl>
        <dt>Title:
        <dd><input type=text size=30 name=title>
        <dt>Text:
        <dd><textarea name=text rows=5 cols=40></textarea>
        <dd><input type=submit value=Share>
      </dl>
    </form>
  {% endif %}
  <ul class=entries>
  {% for entry in entries %}
    <li><h2>{{ entry.title }}</h2>{{ entry.text|safe }}
  {% else %}
    <li><em>Unbelievable.  No entries here so far</em>
  {% endfor %}
  </ul>
{% endblock %}

运行结果

debug运行,访问http://localhost:5000/show_entries我们大概能看到如下的界面,
这里写图片描述
如果能看到这个界面,基本就算是成功了,至于代码里边各个方法,各个模块都是是吗功能,我也不知道,自己查吧。
源码下载地址: mysql-flask下载地址

发布了176 篇原创文章 · 获赞 84 · 访问量 44万+

猜你喜欢

转载自blog.csdn.net/lovemenghaibin/article/details/79250300