Flask开发博客(上)

96
Andrew_liu
2015.05.13 13:21* 字数 502

本博客采用创作共用版权协议, 要求署名、非商业用途和保持一致. 转载本博客文章必须也遵循署名-非商业用途-保持一致的创作共用协议.

Flask博客源码公开在Github

博客欢迎界面
博客主页

缘起

最近想读读python方向的源码, 想Pythonic一点, 左右看去, 最后决定读Flask源码.

既然决定读源码, 我认为首先要简单的了解:

  • 框架的功能
  • 具体接口
  • 实现一个简单的轮子.

Flask我就不多介绍了, 网上一搜一大把, python几大著名Web框架之一, 以其轻量级, 高可扩展性而著名.

那么我们开始造轮子之旅吧

环境相关:
Mac OS X 10.10.3
Sublime Text 3
FLask 0.10.1
Python 3.4.1 # 请放手Python2.7.8, 拥抱Python3

下文主要内容:

  • 介绍Flask搭建博客依赖(随着文章的圆满, 会逐渐添加)
  • 搭建博客欢迎页面
  • 搭建博客基本框架

Flask安装及相关插件

框架及插件:

数据库:

  • mongo(了解并会使用一种NoSQL会有很大的好处)

环境配置

$ pip install virtualenv
$ virtualenv -p /usr/local/bin/python3.4 Flask
$ source Flask/bin/activate
$ pip install Flask, Flask-Script, Flask-WTF, flask-mongoengine

项目骨架

请根据下面的Tree文件结构建立文件夹和文件

$ tree ./

./
├── README.md
├── app/
│   ├── __init__.py
│   ├── models.py
│   ├── static/
│   ├── templates/
│   └── views.py
├── config.py
├── manage.py
├── requirements.txt
  • app为项目核心源码
  • static为项目静态文件
  • templates为项目HTML模板

Hello World

国际惯例, 编程第一步...

$ vim app/__init__.py

# -*- coding: utf-8 -*-
#!/usr/bin/env python

from flask import Flask

app = Flask(__name__)  #创建Flask类的实例
app.config.from_object("config")  #从config.py读入配置

#这个import语句放在这里, 防止views, models import发生循环import
from app import views, models  

views.py用于便携Blog的主逻辑, 和Django中views.py功能相同

$ vim app/views.py

# -*- coding: utf-8 -*-
#!/usr/bin/env python

from app import app
from flask import render_template

@app.route('/')
def index():
    return "Hello World!"

运用Flask-Script为Flask编写服务器脚本, 产生类似Django的运行方式

$vim manage.py
# -*- coding: utf-8 -*-
#!/usr/bin/env python

from flask.ext.script import Manager, Server
from app import app

manager = Manager(app)
manager.add_command("runserver", 
        Server(host="127.0.0.1", port=5000, use_debugger=True))

if __name__ == '__main__':
    manager.run()

运行服务器

$ python manage.py flask

浏览器打开http://127.0.0.1:5000/, 正式踏出第一步...

博客搭建框架

编写欢迎页面及样式

$ vim app/templates/welcome.html

<html>
  <head>
    {% if title %}
    <title>{{ title }} - 雪忆</title>
    {% else %}
    <title>雪忆</title>
    {% endif %}
    <link rel="stylesheet" href="http://yui.yahooapis.com/pure/0.6.0/pure-min.css">
    <link rel="stylesheet" href="{{ url_for('static', filename='welcome.css') }}">
</head>
<body>
<div id="wrapper">
  <div id="info">
    <div id="info-content">
      <h1><strong>Andrew Liu</strong> 雪  忆</h1>
      <p>雪忆, 如雪般单纯, 冷静思考.</p>
    </div>
  </div>
</div><!-- #wrapper -->
</body>
</html>
$ vim app/static/welcome.css

/* reset */
* {
  margin: 0;
  padding: 0;
}

#wrapper {
  position: absolute;
  width: 100%;
  height: 100%;
  overflow: hidden;
}

label {
  cursor: pointer;
}
label:focus {
  outline: none;
}

/* for show */
html, body {
  height: 100%;
}

body {
  background: url(http://37.media.tumblr.com/f6c67ec2821a91051e4175f8a102e1e2/tumblr_n6rzpcsMk41st5lhmo1_1280.jpg) 50% 50%/cover;
}

p {
  margin-bottom: 15px;
}

#info {
  display: table;
  background: rgba(0, 0, 0, 0.4);
  height: 100%;
  width: 100%;
}
#info #info-content {
  display: table-cell;
  vertical-align: middle;
  text-align: center;
  text-transform: uppercase;
  color: #fff;
  font-size: 12px;
}
#info #info-content h1 {
  color: #fff;
  border: 3px solid #fff;
  text-align: center;
  background: rgba(0, 0, 0, 0.1);
  font-size: 22px;
  font-weight: normal;
  padding: 20px;
  margin: 10px;
  display: inline-block;
}
#info #info-content h1 strong {
  display: block;
  font-size: 26px;
}

现在更改views.py

# -*- coding: utf-8 -*-
#!/usr/bin/env python

from app import app
from flask import render_template, url_for

@app.route('/')
def index():
    return render_template('welcome.html', title="Welcome")

到现在为止我们已经完成了欢迎页面的搭建

编写博客主页框架和样式

$ vim  app/templates/base.html
<html>
  <head>
    {% if title %}
    <title>{{ title }} - 雪忆</title>
    {% else %}
    <title>雪忆</title>
    {% endif %}
    <link rel="stylesheet" href="http://yui.yahooapis.com/pure/0.6.0/pure-min.css">
    <link rel="stylesheet" href="{{ url_for('static', filename='base.css') }}">
</head>
<body>
<header class="header">
  <ul>
    <li class="cor-1"></li>
    <li class="cor-2"></li>
    <li class="cor-3"></li>
    <li class="cor-4"></li>
    <li class="cor-5"></li>
  </ul>
  </header>
<div class="wrap">
  

<nav class="menu">
  <ul>
    <li>
      <a href="#">Home</a>
    </li>
    <li>
      <a href="#">Archive</a>
    </li>
    <li>
      <a href="#">About me</a>
    </li>
  </ul>
  </nav>
    <aside class="sidebar">
      <div class="widget">
      <h2>Michael</h2>
      <p>Hello, my name’s <b>Andrew Liu</b>. I’m 23 years old. I live in <b>NanJing (China)</b>. I am a <b>Pythoner</b>.<br> Contact Me:<br><b>liu.bin.coder@gmail.com</b></p>
      </div>
      <div class="widget">
      <h2>Title</h2>
      <p>Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua.</p>
      </div>

  </aside>
    {% block content %}{% endblock %}
</div>
</body>
</html>
$vim app/static/base.css

@import url(http://fonts.googleapis.com/css?family=Open+Sans:400,800,700,600,300);

body {
  margin:0;
  font-family: 'Open Sans', sans-serif;
  background: #eee;
}

hr {
  background:#dedede;
  border:0;
  height:1px;
}

.header {
  overflow: hidden;
  display:block;
  position:fixed;
  top:0;
  margin:0;
  width:100%;
  height:4px;
  text-align:center;
}

.header ul {
  margin:0;
  padding:0;
}

.header ul li {
  overflow:hidden;
  display:block;
  float:left;
  width:20%;
  height:4px;
}

.header .cor-1 {
  background:#f1c40f;
}

.header .cor-2 {
  background:#e67e22;
}

.header .cor-3 {
  background:#e74c3c;
}

.header .cor-4 {
  background:#9b59b6;
}

.header .cor-5 {
  background-color: hsla(10,40%,50%,1);
}

.wrap {
  width: 950px;
  margin:25px auto;
}

nav.menu ul {
  overflow:hidden;
  float:left;
  width: 650px;
  padding:0;
  margin:0 0 0;
  list-style: none;
  color:#fff;
  background: #1abc9c;
    -webkit-box-shadow: 1px 1px 1px 0px rgba(204,204,204,0.55);
  -moz-box-shadow: 1px 1px 1px 0px rgba(204,204,204,0.55);
  box-shadow: 1px 1px 1px 0px rgba(204,204,204,0.55);
}

nav.menu ul li {
  float:left;
  margin:0;
}

nav.menu ul a {
  display:block;
  padding:25px;
  font-size: 16px;
  font-weight:600;
  text-transform: uppercase;
  color:#fff;
  text-decoration: none;
  transition: all 0.5s ease;
}

nav.menu ul a:hover {
  background:#16a085;
  text-decoration: underline;
}

.sidebar {
  width:275px;
  float:right;
}

.sidebar .widget {
  margin:0 0 25px;
  padding:25px;
  background:#fff;
  transition: all 0.5s ease;
  border-bottom: 2px solid #fff;
}

.sidebar .widget:hover {
  border-bottom: 2px solid #3498db;
}

.sidebar .widget h2 {
  margin:0 0 15px;
  padding:0;
  text-transform: uppercase;
  font-size: 18px;
  font-weight:800;
  color:#3498db;
}

.sidebar .widget p {
  font-size: 14px;
}

.sidebar .widget p:last-child {
  margin:0;
}

.blog {
  float:left;
}

.conteudo {
  width:600px;
  margin:25px auto;
  padding:25px;
  background: #fff;
  border:1px solid #dedede;
  -webkit-box-shadow: 1px 1px 1px 0px rgba(204,204,204,0.35);
  -moz-box-shadow: 1px 1px 1px 0px rgba(204,204,204,0.35);
  box-shadow: 1px 1px 1px 0px rgba(204,204,204,0.35);
}

.conteudo img {
  margin:0 0 25px -25px;
  max-width: 650px;
  min-width: 650px;
}

.conteudo h1 {
  margin:0 0 15px;
  padding:0;
  font-family: Georgia;
  font-weight: normal;
  color: #666;
}

.conteudo p:last-child {
  margin: 0;
}

.conteudo .continue-lendo {
  color:#000;
  font-weight: 700; 
  text-decoration: none;
  transition: all 0.5s ease;
}

.conteudo .continue-lendo:hover {
  margin-left:10px;
}

.post-info {
  float: right;
  margin: -10px 0 15px;
  font-size: 12px;
  text-transform: uppercase;
}

@media screen and (max-width: 960px) {
  
  .header {
  position:inherit;
}
  
.wrap {
  width: 90%;
  margin:25px auto;
}
.sidebar {
  width:100%;
  float:right;
    margin:25px 0 0;
}
  
 .sidebar .widget {
  padding:5%;
}
  
  nav.menu ul {
  width: 100%;
}
  
    nav.menu ul {
  float:inherit;
}
  
  nav.menu ul li {
  float:inherit;
  margin:0;
}
  
nav.menu ul a {
  padding:15px;
  font-size: 16px;
  border-bottom:1px solid #16a085;
  border-top:1px solid #1abf9f;
}
  
.blog {
  width:90%;
}
  
.conteudo {
  float:inherit;
  width:101%;
  padding:5%;  
  margin:0 auto 25px;
  background: #fff;
  border:1px solid #dedede;
}

.conteudo img {
  margin:0 0 25px -5%;
  max-width: 110%;
  min-width: 110%;
}
  
    .conteudo .continue-lendo:hover {
  margin-left:0;
}


}

@media screen and (max-width: 460px) {
 
  nav.menu ul a {
  padding:15px;
  font-size: 14px;
}
  
.sidebar {
  display:none
}
  .post-info {
  display:none;
}
  
  .conteudo {
  margin:25px auto;
  }
  
  .conteudo img {
  margin:-5% 0 25px -5%;
}
}

在views.py编写主页测试代码

# -*- coding: utf-8 -*-
#!/usr/bin/env python

from app import app
from flask import render_template, url_for

@app.route('/')
def index():
    return render_template('welcome.html', title="Welcome")

@app.route('/home')
def home():
    return render_template('base.html', title="Home")

打开浏览器, 访问http://127.0.0.1:5000/home, 你会看到精美小清新的主页框架

Flask之殇
Gupao