Skip to content

Commit 7efaa17

Browse files
committed
示例项目
1 parent 00b0c6e commit 7efaa17

File tree

24 files changed

+591
-1
lines changed

24 files changed

+591
-1
lines changed

step5-Python-web/Flask/README.md

Lines changed: 59 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -173,6 +173,7 @@
173173
```bash
174174
├── 项目文件夹
175175
│ ├── app.py # 程序运行主入口
176+
│ ├── forms.py # 前端表单数据获取
176177
│ ├── static # 静态文件存放文件夹
177178
│ │ ├── css
178179
│ │ ├── js
@@ -189,6 +190,8 @@
189190
│ │ ├── index.html
190191
```
191192

193+
> 本章 demo,[访问](project)
194+
192195
### 📝 模板语言
193196

194197
+ 变量
@@ -320,7 +323,62 @@
320323

321324
> GitHub:<https://github.com/lepture/flask-wtf>
322325

323-
+
326+
+ `forms.py`
327+
328+
```python
329+
#coding=utf-8
330+
331+
from flask_wtf import FlaskForm
332+
from wtforms import StringField, TextAreaField, SubmitField, SelectField, RadioField
333+
from wtforms.validators import DataRequired
334+
335+
336+
class NewsForm(FlaskForm):
337+
# 新闻表单
338+
title = StringField(label='新闻标题', validators=[DataRequired('请输入标题')],
339+
description='请输入标题',
340+
render_kw={'required': 'required', 'class': 'form-control'})
341+
content = TextAreaField(label='新闻内容', validators=[DataRequired('请输入内容')],
342+
description='请输入内容',
343+
render_kw={'required': 'required', 'class': 'form-control'})
344+
types = SelectField('新闻类型',
345+
choices=[('推荐', '推荐'), ('百家', '百家'), ('本地', '本地'), ('图片', '图片')])
346+
image = StringField(label='新闻图片',
347+
description='请输入图片地址',
348+
render_kw={'required': 'required', 'class': 'form-control'})
349+
submit = SubmitField('提交')
350+
```
351+
352+
+ `app.py`
353+
354+
```python
355+
...
356+
from flask import Flask, render_template, redirect, url_for
357+
from forms import NewsForm
358+
from datetime import datetime
359+
360+
app.config['SECRET_KEY'] = 'a random string'
361+
...
362+
363+
@app.route('/admin/add/', methods=('GET', 'POST'))
364+
def add():
365+
# 新闻后台数据新增
366+
form = NewsForm()
367+
if form.validate_on_submit():
368+
# 获取数据
369+
new_obj = News(
370+
title = form.title.data,
371+
content = form.content.data,
372+
types = form.types.data,
373+
image = form.image.data,
374+
created_at = datetime.now()
375+
)
376+
# 保存数据
377+
db.session.add(new_obj)
378+
db.session.commit()
379+
return redirect(url_for('admin'))
380+
return render_template('admin/add.html', form=form)
381+
```
324382

325383
### 🔍 实现增删改查
326384

Lines changed: 108 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,108 @@
1+
from flask import Flask, render_template, redirect, url_for
2+
from flask_sqlalchemy import SQLAlchemy
3+
4+
from forms import NewsForm
5+
from datetime import datetime
6+
7+
app = Flask(__name__)
8+
app.config['SQLALCHEMY_DATABASE_URI'] = 'mysql://root:fmw19990718@localhost:3306/net_news?charset=utf8'
9+
app.config['SECRET_KEY'] = 'a random string'
10+
db = SQLAlchemy(app)
11+
12+
class News(db.Model):
13+
__tablename__ = 'news'
14+
id = db.Column(db.Integer, primary_key=True)
15+
title = db.Column(db.String(200), nullable=False)
16+
content = db.Column(db.String(2000), nullable=False)
17+
types = db.Column(db.String(10), nullable=False)
18+
image = db.Column(db.String(300), )
19+
author = db.Column(db.String(20), )
20+
view_count = db.Column(db.Integer)
21+
created_at = db.Column(db.DateTime)
22+
is_valid = db.Column(db.Boolean)
23+
24+
def __repr__(self):
25+
return '<News %r>' % self.title
26+
27+
28+
@app.route('/')
29+
def index():
30+
# 新闻首页
31+
# news_list = News.query.all()
32+
news_list = News.query.filter_by(is_valid=1)
33+
return render_template('index.html', news_list=news_list)
34+
35+
@app.route('/cat/')
36+
@app.route('/cat/<name>/')
37+
def cat(name=None):
38+
# 新闻类别,查询类别为 name 的新闻数据
39+
news_list = News.query.filter(News.types==name)
40+
return render_template('cat.html', name=name, news_list=news_list)
41+
42+
@app.route('/detail/<int:pk>/')
43+
def detail(pk):
44+
# 新闻详情信息
45+
news_obj = News.query.get(pk)
46+
return render_template('detail.html', news_obj=news_obj)
47+
48+
@app.route('/admin/')
49+
@app.route('/admin/<int:page>/')
50+
def admin(page=None):
51+
# 新闻后台管理首页
52+
if page is None:
53+
page = 1
54+
news_list = News.query.filter_by(is_valid=True).paginate(page=page, per_page=5)
55+
return render_template('admin/index.html', news_list=news_list)
56+
57+
@app.route('/admin/add/', methods=('GET', 'POST'))
58+
def add():
59+
# 新闻后台数据新增
60+
form = NewsForm()
61+
if form.validate_on_submit():
62+
# 获取数据
63+
new_obj = News(
64+
title = form.title.data,
65+
content = form.content.data,
66+
types = form.types.data,
67+
image = form.image.data,
68+
created_at = datetime.now(),
69+
is_valid = True
70+
)
71+
# 保存数据
72+
db.session.add(new_obj)
73+
db.session.commit()
74+
return redirect(url_for('admin'))
75+
return render_template('admin/add.html', form=form)
76+
77+
@app.route('/admin/update/<int:pk>/', methods=('GET', 'POST'))
78+
def update(pk):
79+
# 新闻后台数据修改
80+
news_obj = News.query.get(pk)
81+
# 如果没有数据,则返回
82+
if not news_obj:
83+
return redirect(url_for('admin'))
84+
form = NewsForm(obj=news_obj)
85+
if form.validate_on_submit():
86+
# 获取数据
87+
news_obj.title = form.title.data
88+
news_obj.content = form.content.data
89+
# 保存数据
90+
db.session.add(news_obj)
91+
db.session.commit()
92+
return redirect(url_for('admin'))
93+
return render_template('admin/update.html', form=form)
94+
95+
@app.route('/admin/delete/<int:pk>/', methods=('GET', 'POST'))
96+
def delete(pk):
97+
# 新闻后台数据删除
98+
news_obj = News.query.get(pk)
99+
if not news_obj:
100+
return 'no'
101+
news_obj.is_valid = False
102+
db.session.add(news_obj)
103+
db.session.commit()
104+
return 'yes'
105+
106+
107+
if __name__ == "__main__":
108+
app.run(debug=True)
Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
#coding=utf-8
2+
3+
from flask_wtf import FlaskForm
4+
from wtforms import StringField, TextAreaField, SubmitField, SelectField, RadioField
5+
from wtforms.validators import DataRequired
6+
7+
8+
class NewsForm(FlaskForm):
9+
# 新闻表单
10+
title = StringField(label='新闻标题', validators=[DataRequired('请输入标题')],
11+
description='请输入标题',
12+
render_kw={'required': 'required', 'class': 'form-control'})
13+
content = TextAreaField(label='新闻内容', validators=[DataRequired('请输入内容')],
14+
description='请输入内容',
15+
render_kw={'required': 'required', 'class': 'form-control'})
16+
types = SelectField('新闻类型',
17+
choices=[('推荐', '推荐'), ('百家', '百家'), ('本地', '本地'), ('图片', '图片')])
18+
image = StringField(label='新闻图片',
19+
description='请输入图片地址',
20+
render_kw={'required': 'required', 'class': 'form-control'})
21+
submit = SubmitField('提交')

step5-Python-web/Flask/project/static/css/bootstrap.min.css

Lines changed: 6 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.
Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
header > nav {
2+
text-align: center;
3+
}
4+
5+
header > nav > ul {
6+
display: inline;
7+
white-space: nowrap;
8+
}
9+
10+
header > nav > ul > li {
11+
list-style: none;
12+
padding: 10px 20px;
13+
display: inline-block;
14+
background: pink;
15+
white-space: nowrap;
16+
17+
border: 1px solid;
18+
}
19+
20+
article {
21+
text-align: center;
22+
}
23+
24+
.list-news {
25+
border: 1px solid black;
26+
margin-top: 10px;
27+
}
23.6 KB
Loading
11.1 KB
Loading
7.33 KB
Loading
13.6 KB
Loading
9.94 KB
Loading

0 commit comments

Comments
 (0)