이전에 플라스크 개발 환경 설정에 대한 기사를 쓴 적이 있습니다. 오늘은 블로그 시스템이라는 실용적인 소규모 프로젝트를 계속하겠습니다.
블로그 시스템은 페이지가 하나만 있을 정도로 매우 간단하며, 작은 크기에도 불구하고 모든 기능을 갖추고 있습니다. 여기서의 목적은 프로젝트를 하기 위해 프로젝트를 하는 것이 아닙니다. 이 글의 원래 의도는 이 연습을 통해 다음과 같은 지식 포인트를 전달하는 것입니다.
1. 글로벌 관점에서 플라스크 프로젝트의 디렉토리 구조를 이해합니다
2. 플라스크 프로젝트의 작동 메커니즘
3. MVC 아키텍처를 구현하는 Flask 프레임워크
4. mysql 데이터베이스를 운영하는 sqlalchemy
1. 새로운 프로젝트: 블로그 시스템
pycharm에서 아래와 같이 새 플라스크 프로젝트를 만듭니다.
완성된 디렉터리 구조는 다음과 같습니다. 매우 간단합니다. 정적 폴더, 템플릿 폴더, py 파일
위 디렉토리 구조는 플라스크의 초기 구조입니다. 규모가 크고 복잡한 프로젝트의 경우에는 패키지 관리 및 MVC 아키텍처 설계를 도입해야 합니다.
2. 디렉토리 구조 재구성 및 패키지 관리 도입
위 구조의 경우 최상위 blog3 디렉토리에
1. 프로젝트의 통합 항목 파일로 새 runserver.py 파일을 생성합니다
2. 새 블로그 폴더를 만들고 기존 정적, 템플릿, blog3.py를 블로그 폴더로 옮긴 다음 컨트롤러 폴더와 모델 폴더를 각각 만듭니다. blog3.py의 이름을 __init__.py로 바꾸세요.
이제 디렉토리는 다음과 같습니다.
이는 대규모 엔지니어링 구조와 동일합니다.
1) 최상위 blog2 디렉토리는 프로젝트 이름입니다. 프로젝트에는 여러 모듈, 즉 애플리케이션이 포함될 수 있습니다. 각 애플리케이션에는 자체 구성 파일, 초기화 파일 및 MVC 아키텍처가 있습니다.
2) runserver.py: 애플리케이션 모듈과 동일한 레벨, 프로젝트 시작 파일
3) 2차 blog2 디렉터리: 모듈 이름
컨트롤러 디렉토리: MVC의 C, 주로 뷰 기능을 저장합니다
모델 디렉터리: MVC의 M은 주로 엔터티 클래스 파일과 맵 테이블을 데이터베이스에 저장합니다.
템플릿: MVC의 V, html 파일 저장
정적: 정적 파일, 주로 CSS, JS 및 기타 파일을 저장합니다.
__init__.py: 모듈 초기화 파일, Flask __init__.py 파일에서 프로그램 개체 생성이 완료되어야 각 패키지를 안전하게 가져오고 참조할 수 있습니다.
Setting.py: 구성 파일, 데이터베이스 사용자 이름 및 비밀번호 등
3. 개발코드
1. 먼저 프로젝트를 실행하세요.
1) __init__.py 파일을 작성하고 프로젝트 객체를 생성합니다.
# -*- coding: utf-8 -*- from flask import Flask #创建项目对象 app = Flask(__name__)
2) runserver.py 파일에 다음 코드를 추가합니다.
from blog3 import app @app.route('/') def hello_world(): return 'Hello World!' if __name__ == '__main__': app.run(debug=True)
3) runserver.py 파일을 실행합니다:
그런 다음 브라우저에 http://127.0.0.1:5000/을 입력하면 helloworld라는 단어가 표시됩니다
이제 프로젝트의 프로토타입이 정상적으로 실행될 수 있습니다. 다음으로 할 일은 프로젝트를 충실하게 만들기 위한 콘텐츠를 추가하는 것입니다.
2. 디자인 데이터베이스
이 연습은 테이블 2개, 사용자 테이블 1개, 기사 테이블 1개만 사용하여 상대적으로 간단합니다. 우리는 Python의 ORM 프레임워크인 플라스크-sqlalchemy를 사용하여 테이블 생성, 추가, 삭제, 수정 및 쿼리 기능을 구현합니다.
다음 내용이 포함된 User.py 및 Category.py 파일을 모델 폴더에 추가합니다.
1) User.py:
from blog2 import db class User(db.Model): __tablename__ = 'b_user' id = db.Column(db.Integer,primary_key=True) username = db.Column(db.String(10),unique=True) password = db.Column(db.String(16)) def __init__(self,username,password): self.username = username self.password = password def __repr__(self): return '<User %r>' % self.username
2) Category.py
from blog2 import db class Category(db.Model): __tablename__ = 'b_category' id = db.Column(db.Integer,primary_key=True) title = db.Column(db.String(20),unique=True) content = db.Column(db.String(100)) def __init__(self,title,content): self.title = title self.content = content def __repr__(self): return '<Category %r>' % self.title
3) 모듈 디렉터리 blog2에 새 settings.py 파일을 생성하고 데이터베이스 연결 정보를 구성합니다
# _*_ coding: utf-8 _*_ #调试模式是否开启 DEBUG = True SQLALCHEMY_TRACK_MODIFICATIONS = False #session必须要设置key SECRET_KEY='A0Zr98j/3yX R~XHH!jmN]LWX/,?RT' #mysql数据库连接信息,这里改为自己的账号 SQLALCHEMY_DATABASE_URI = "mysql://username:password@ip:port/dbname"
4) 프로젝트가 구성 파일을 읽도록 합니다
__init__.py 수정: 다음 내용 추가(빨간색 부분):
# -*- coding: utf-8 -*- from flask import Flask from flask_sqlalchemy import SQLAlchemy app = Flask(__name__)#import os#print os.environ.keys()#print os.environ.get('FLASKR_SETTINGS')#加载配置文件内容app.config.from_object('blog2.setting') #模块下的setting文件名,不用加py后缀 app.config.from_envvar('FLASKR_SETTINGS') #环境变量,指向配置文件setting的路径#创建数据库对象 db = SQLAlchemy(app)
참고: FLASKR_SETTINGS 환경 변수는 별도로 수동으로 설정해야 합니다. 창 아래의 명령줄에 입력할 수 있습니다.
E:\workdir\blog2> set FLASKR_SETTINGS=E:\workdir\blog2\blog2\setting.py
또는 내 컴퓨터-->고급-->환경 변수를 클릭하여 새 변수를 만듭니다.
5) 데이터베이스 및 테이블 생성
Windows 명령줄 모드에서 runserver.py 프로젝트 디렉터리로 이동하고 Python 셸을 입력하세요.
빨간색 부분을 입력하세요:
E:\workdir\blog2>python Python 2.7.10 (default, May 23 2015, 09:44:00) [MSC v.1500 64 bit (AMD64)] on wi n32 Type "help", "copyright", "credits" or "license" for more information. >>> from blog2 import db >>> db.create_all() >>> >>>
오류 출력이 없으면 데이터베이스와 테이블이 성공적으로 생성되었음을 의미합니다. 이때 데이터베이스로 이동하여 다음을 확인합니다.
数据库已经存在了,再看看表情况:发现没有对应的b_user和b_category表。这是为什么呢?是不是没有找到model目录下的两个类呢。问题在于:__init__.py文件没有引入model包,导致__init__.py无法找到实体类。记住:一切模块对象的创建都在__init__.py中完成
在blog2目录下的__init__.py添加如下代码:
#只有在app对象之后声明,用于导入model否则无法创建表 from blog2.model import User,Category
再次运行上面命令:db.create_all()方法。这时表已经创建成功了。
3、添加界面模板:如登陆页面,显示blog文章页面,添加blog页面
在templates目录下添加三个html文件:
layout.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>
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 %}
show_entries.html:
{% extends "layout.html" %} {% block body %} {% if session.logged_in %} <form action="{{ url_for('add_entry') }}" method='POST' class=add-entry> <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.content|safe }} {% else %} <li><em>Unbelievable. No entries here so far</em> {% endfor %} </ul> {% endblock %}
对应static中添加css文件:style.css
body { font-family: sans-serif; background: #eee; } a, h1, h2 { color: #377BA8; } h1, h2 { font-family: 'Georgia', serif; margin: 0; } h1 { border-bottom: 2px solid #eee; } h2 { font-size: 1.2em; } .page { margin: 2em auto; width: 35em; border: 5px solid #ccc; padding: 0.8em; background: white; } .entries { list-style: none; margin: 0; padding: 0; } .entries li { margin: 0.8em 1.2em; } .entries li h2 { margin-left: -1em; } .add-entry { font-size: 0.9em; border-bottom: 1px solid #ccc; } .add-entry dl { font-weight: bold; } .metanav { text-align: right; font-size: 0.8em; padding: 0.3em; margin-bottom: 1em; background: #fafafa; } .flash { background: #CEE5F5; padding: 0.5em; border: 1px solid #AACBE2; } .error { background: #F0D6D6; padding: 0.5em; }
4、添加业务逻辑
在controller目录下新建blog_message.py文件:
from blog2.model.User import User from blog2.model.Category import Category import os from blog2 import app,db from flask import request,render_template,flash,abort,url_for,redirect,session,Flask,g @app.route('/') def show_entries(): categorys = Category.query.all() return render_template('show_entries.html',entries=categorys) @app.route('/add',methods=['POST']) def add_entry(): if not session.get('logged_in'): abort(401) title = request.form['title'] content = request.form['text'] category = Category(title,content) db.session.add(category) db.session.commit() flash('New entry was successfully posted') return redirect(url_for('show_entries')) @app.route('/login',methods=['GET','POST']) def login(): error = None if request.method == 'POST': username = request.form['username'] password = request.form['password'] user = User.query.filter_by(username=request.form['username']).first() passwd = User.query.filter_by(password=request.form['password']).first() if user is None: error = 'Invalid username' elif passwd is None: 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('/logout') def logout(): session.pop('logged_in', None) flash('You were logged out') return redirect(url_for('show_entries'))
千万不要忘了在模块级目录下(blog2目录)的__init__.py文件引入视图模块,代码如下:
#只有在app对象之后声明,用于导入view模块 from blog2.controller import blog_manage
5、运行项目,效果如下:
1)输入http://127.0.0.1:5000/,正常情况下你的应该是空白的,因为还没有任何数据。
2)点击log in
忘了告诉你了,你要事先在b_user表中添加一个用户喔,因为登陆要验证用户的,否则你是无法登陆成功的。
3) 添加条目
以上就是这个小项目的所有页面,很简单吧。你一定能搞定!!!
【总结】:通过本次练习,是否对flask框架运行机制有所了解呢,是不是已经有了全局的认识了,如果ok,那么这个小练习就有存在价值了。
参考文献:
【flask快速入门中文版】http://docs.jinkan.org/docs/flask/
【flask快速入门英文版】http://flask.pocoo.org/docs/0.11/
【flask-sqlalchemy中文版】http://www.pythondoc.com/flask-sqlalchemy/index.html
【flask-sqlalchemy英文版】http://flask-sqlalchemy.pocoo.org/2.1/