Flask开发博客(上)

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

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, 你会看到精美小清新的主页框架

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 161,601评论 4 369
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 68,367评论 1 305
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 111,249评论 0 254
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 44,539评论 0 217
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 52,967评论 3 295
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 40,929评论 1 224
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 32,098评论 2 317
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 30,825评论 0 207
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 34,609评论 1 249
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 30,796评论 2 253
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 32,282评论 1 265
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 28,603评论 3 261
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 33,277评论 3 242
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 26,159评论 0 8
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 26,959评论 0 201
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 36,079评论 2 285
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 35,874评论 2 277

推荐阅读更多精彩内容